一、钩子函数与上下文处理器
from flask import Flask,Response,request,session,render_template,g
import config
from exts import db,mail
from blueprints import qa_bp
from blueprints import user_bp
from flask_migrate import Migrate
from models import UserModel
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(user_bp)
#钩子函数
@app.before_request
def before_request():
user_id=session.get("user_id")
if user_id:
try:
user = UserModel.query.get(user_id)
#给g绑定一个叫做user的变量,它的值是user这个变量
#setattr(g,"user",user)
g.user=user
except:
g.user=None
#请求来了-> before_request->视图函数->视图函数中返回的模板->context_processor
#上下文处理器
@app.context_processor
def context_processor():
if hasattr(g,"user"):
return {"user":g.user}
else:
return {}
if __name__ =='__main__':
app.run(debug=True)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}{% endblock %}</title>
<link rel="stylesheet" href="{{url_for('static',filename='bootstrap/bootstrap@4.6.min.css')}}">
<link rel="stylesheet" href="{{url_for('static',filename='css/init.css')}}">
{% block head %} {% endblock %}
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container">
<a class="navbar-brand" href="#">问答</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="#">首页 <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">发布问答</a>
</li>
<li class="nav-item ml-2">
<form class="form-inline my-2 my-lg-0">
<input class="form-control mr-sm-2" type="search" placeholder="关键字" aria-label="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">搜索</button>
</form>
</li>
</ul>
<ul class="navbar-nav">
{% if user %}
<li class="nav-item">
<spam class="nav-link">{{user.username}}</spam>
</li>
<li class="nav-item">
<a class="nav-link" href="{{url_for('user.register')}}">退出登录</a>
</li>
{% else %}
<li class="nav-item">
<a class="nav-link" href="{{url_for('user.login')}}">登录 </a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{url_for('user.register')}}">注册</a>
</li>
{% endif %}
</ul>
</div>
</nav>
</div>
<div class="container">{% block body %}{% endblock %}</div>
</nav>
</body>
</html>
登录后会是这样的页面:
而没登陆是这样的:
二、退出登录功能
import random
import string
from flask import Blueprint,render_template,request,redirect,url_for,jsonify,session,flash
from exts import mail,db
from flask_mail import Message
from models import EmailCaptchaModel,UserModel
from datetime import datetime
from .forms import RegisterForm
from werkzeug.security import generate_password_hash,check_password_hash
bp=Blueprint("user",__name__,url_prefix="/user")
#实现登录功能
@bp.route("/login",method=['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 user and check_password_hash(user.password,password):
session['user_id']=user.id
return redirect("/")
else:
flash("邮箱和密码不匹配!")
return redirect(url_for("user.login"))
else:
flash("邮箱或密码格式错误!")
return redirect(url_for("user.login"))
@bp.route("/register",methods=['GET','POST'])
def register():
if request.method =='GET':
return render_template("register.html")
else:
form = RegisterForm(request.form)
if form.validate():
email = form.email.data
username = form.username.data
password = form.password.data
hash_password=generate_password_hash(password) #密码加密
user = UserModel(email=email, username=username, password=password)
db.session.add(user)
db.session.commit()
return redirect(url_for("user.login"))
else:
return redirect(url_for("user.register"))
#退出登录
@bp.route("/logout")
def logout():
#清除session中所有的数据
session.clear()
return redirect(url_for('user.login'))
@bp.route("/captcha",methods=['POST'])
def get_captcha():
email=request.form.get("email")
letter=string.ascii_letters+string.digits
captcha="".join(random.sample(letter,4))
if email:
message = Message(
subject='邮箱测试',
recipients=['2780038443@qq.com'],
body=f"您的注册验证码是:{captcha},请不要告诉任何人哦!"
)
mail.send(message)
captcha_model=EmailCaptchaModel.query.filter_by(email=email).first()
if captcha_model:
captcha_model.captcha=captcha
captcha_model.create_time=datetime.now()
db.session.commit()
else:
captcha_model=EmailCaptchaModel(email=email,captcha=captcha)
db.session.add(captcha_model)
db.session.commit()
#code:200。成功的,正常的请求
return jsonify({"code":200})
else:
#code:400 客户端错误
return jsonify({"code":400,"message":"请先传递邮箱!"})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}{% endblock %}</title>
<link rel="stylesheet" href="{{url_for('static',filename='bootstrap/bootstrap@4.6.min.css')}}">
<link rel="stylesheet" href="{{url_for('static',filename='css/init.css')}}">
{% block head %} {% endblock %}
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container">
<a class="navbar-brand" href="#">问答</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="#">首页 <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">发布问答</a>
</li>
<li class="nav-item ml-2">
<form class="form-inline my-2 my-lg-0">
<input class="form-control mr-sm-2" type="search" placeholder="关键字" aria-label="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">搜索</button>
</form>
</li>
</ul>
<ul class="navbar-nav">
{% if user %}
<li class="nav-item">
<spam class="nav-link">{{user.username}}</spam>
</li>
<li class="nav-item">
<a class="nav-link" href="{{url_for('user.logout')}}">退出登录</a>
</li>
{% else %}
<li class="nav-item">
<a class="nav-link" href="{{url_for('user.login')}}">登录 </a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{url_for('user.register')}}">注册</a>
</li>
{% endif %}
</ul>
</div>
</nav>
</div>
<div class="container">{% block body %}{% endblock %}</div>
</nav>
</body>
</html>