Flask项目实战-两个钩子函数+登录和退出登录

在app.py中需要添加下面两个勾子函数

1.before_request

from flask import Flask, session, g
@app.before_request
def my_before_request():
    user_id = session.get("user_id")
    if user_id:
        user = UserModel.query.get(user_id)
        setattr(g, "user", user)
    else:
        setattr(g, "user", None)
  • 这个钩子在每个请求处理之前被调用,也就是说,每当有一个新的请求到达 Flask 应用时,before_request 钩子函数就会被执行。
  • 它通常用于执行一些请求前需要处理的通用任务,比如身份验证、权限检查、设置请求上下文等。
  • 在代码中,my_before_request 函数首先尝试从 session 中获取 user_idsession 是 Flask 的一个全局对象,用于在请求之间存储信息。
  • 如果 user_id 存在,函数会尝试从数据库中获取对应的用户对象,并将其设置到 Flask 的 g 对象中。g 对象是一个全局对象,用于在应用上下文中存储临时数据,它在请求处理过程中是持久的。
  • 如果 user_id 不存在,g.user 被设置为 None,表示当前没有用户登录。
  • 这个钩子函数的目的是确保每个请求处理函数都可以访问到当前用户的信息,而不需要每次都去查询。

2.context_processor

from flask import Flask, session, g
@app.context_processor
def my_context_processor():
    return {"user": g.user}
  • 这个钩子用于模板上下文处理,它允许你在渲染模板之前向模板上下文中添加额外的变量。
  • 模板上下文处理器在每次渲染模板之前被调用,可以将一些全局变量或函数添加到模板的上下文中,这样在模板中就可以直接使用这些变量或函数。
  • 在代码中,my_context_processor 函数返回一个字典,其中包含了 g.user。这意味着在任何模板中,都可以直接使用 user 变量,而不需要在每个模板中都显式地传递它。
  • 这样做的好处是简化了模板的编写,因为不需要在每个模板中都传递用户信息,而且可以在模板中直接使用 user 变量,提高了代码的可读性和可维护性。

 3.登录

更改base.html,如果用户已经登录了显示用户和退出登录,如果未登录才显示登录和注册

<ul class="navbar-nav">
                  {% if user %}
                    <li class="nav-item">
                      <span class="nav-link">{{ user.username }}</span>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="{{ url_for('auth.logout') }}">退出登录</a>
                    </li>
                  {% else %}
                    <li class="nav-item">
                      <a class="nav-link" href="{{ url_for('auth.login') }}">登录</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="{{ url_for('auth.register') }}">注册</a>
                    </li>
                  {% endif %}
                </ul>

4.退出登录

上面已经吧退出登录的url制作了,下面需要完善下退出登录的函数

在auth.py中增加退出登录函数

退出登录就是把session清理下就行了

@bp.route("logout")
def logout():
    session.clear()
    return redirect("/")

测试登录与未登录

登录的状态

点击退出登录,会跳转到首页

再次访问http://127.0.0.1:5000/auth/login

会提示没有登录

app.py完整代码

from flask import Flask,session,g
import config
from exts import db,mail
from blueprints.qa import bp as qa_bp
from blueprints.auth import bp as auth_bp
from models import UserModel
from flask_migrate import Migrate


app = Flask(__name__)

app.config.from_object(config)


db.init_app(app)
mail.init_app(app)

#将模型映射到数据库中
migrate = Migrate(app,db)

#注册蓝图
app.register_blueprint(qa_bp)
app.register_blueprint(auth_bp)

@app.before_request
def my_before_request():
    user_id = session.get("user_id")
    if user_id:
        user = UserModel.query.get(user_id)
        setattr(g, "user", user)
    else:
        setattr(g, "user", None)

@app.context_processor
def my_context_processor():
    return {"user": g.user}

if __name__ == '__main__':
    app.run()

auth.py完整代码

from flask import Blueprint,render_template,jsonify,redirect,url_for,session
from exts import mail,db
from flask_mail import Message
from flask import request
import string,random
from models import EmailCaptchaModel,UserModel
from .forms import Registerform,Loginform
from werkzeug.security import generate_password_hash,check_password_hash


# /auth
bp = Blueprint("auth",__name__,url_prefix="/auth")

@bp.route("/login",methods=['GET','POST'])
def login():
    if request.method == "GET":
        return render_template("login.html")
    else:
        form = Loginform(request.form)
        if form.validate():
            email = form.email.data
            password = form.password.data
            user = UserModel.query.filter_by(email=email).first()
            if not user:
                print("邮箱在数据库中不存在!")
                return redirect(url_for("auth.login"))
            #检查密码是否正确
            if check_password_hash(user.password,password):
                #存储session
                #flask中的session,是经过加密后存储到cookie中的
                session['user_id'] = user.id
                return redirect("/")
            else:
                print("密码错误!")
                return redirect(url_for("auth.login"))

        else:
            print(form.errors)
            return redirect(url_for("auth.login"))


@bp.route("/register",methods=['GET','POST']) #即可以使用GET请求,也可以使用POST请求
def register():
    if request.method == "GET":
        return render_template("register.html")
    else:
        #表单验证,flask-wtf:wtfarms
        #验证用户提交的邮箱和验证是否正确
        form = Registerform(request.form)
        if form.validate():
            email = form.email.data
            username = form.username.data
            password = form.password.data
            user = UserModel(email=email,username=username,password=generate_password_hash(password))
            db.session.add(user)
            db.session.commit()
            return redirect(url_for("auth.login"))
        else:
            print(form.errors)
            return redirect(url_for("auth.register"))

@bp.route("logout")
def logout():
    session.clear()
    return redirect("/")

@bp.route("/captcha/email")
def get_email_captcha():
    # /capthca/email/<email>
    # /capthca/email?email=xxx@qq.com
    email = request.args.get("email")
    source = string.digits*4
    captcha = random.sample(source,4)
    captcha = "".join(captcha)
    message = Message(subject="问答平台注册验证码", recipients=[email], body=f"你的验证码是:{captcha}")
    mail.send(message)
    #存储验证码到数据库
    email_captcha = EmailCaptchaModel(email=email,captcha=captcha)
    db.session.add(email_captcha)
    db.session.commit()
    # RESTful API
    result = {"code":200,"message":"","data":None}
    return jsonify(result)

@bp.route("/mail/test")
def mail_test():
    message = Message(subject="邮箱测试",recipients=["507303922@qq.com"],body="这是一条测试邮件")
    mail.send(message)
    return "邮件发送测试"

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值