Skip to content

一、知了教育问答平台项目

一、准备工作

  • 根目录下新建config.py文件,用来存放项目的配置信息
  • 根目录下新建exts.py文件,用来存放项目使用的第三方插件/包的配置信息,解决项目资源循环引用的问题
  • 根目录下新建blueprintspython包,里面存放各类的蓝图

1、蓝图的结构

python
from flask import Blueprint

blueprint=Blueprint("auth",__name__,url_prefix="/auth")

@blueprint.route("/login")
def auth_login():
    return "授权登录"

2、app.py的初步配置

python
# 导入Flask
from flask import Flask
# 导入第三方插件/包的配置信息
from exts import db
# 导入表模型
from models import UserModel
from flask_migrate import Migrate
# 导入项目基本配置
from config import Config
# 导入项目蓝图
from blueprints.qa import blueprint as qa_blueprint
from blueprints.auth import  blueprint as auth_blueprint

app = Flask(__name__)
# 绑定配置文件
app.config.from_object(config)

# 把db和app进行绑定
db.init_app(app)

# 使用 Flask-Migrate 扩展来初始化迁移对
migrate=Migrate(app,db)

# 注册蓝图
app.register_blueprint(qa_blueprint)
app.register_blueprint(auth_blueprint)

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

二、flask实现发送邮箱(以QQ邮箱为例)

1、安装flask-mail

bash
pip install flask-mail

引入:

exts.py文件

python
from flask_mail import  Mail

mail=Mail()

app.py文件

python
from exts import mail

mail.init_app(app)

2、开通QQ邮箱的SMTP服务

开通SMTP服务后,获取密码

3、项目config文件配置邮箱

python
class Config:
    # xxxxxx
    # 邮箱配置
    MAIL_SERVER = "smtp.qq.com"
    MAIL_USE_SSL = True
    # 端口 465 是 SMTPS(SMTP over SSL/TLS)的默认端口号。SMTPS 是一种安全的 SMTP 协议,用于通过加密通道传输电子邮件。SMTPS 使用 SSL(Secure Sockets Layer)或 TLS(Transport Layer Security)加密协议来保护邮件的传输安全性。
    MAIL_PORT = 465
    MAIL_USERNAME = "xxxxx@qq.com"
    MAIL_PASSWORD = "xxxxx"
    MAIL_DEFAULT_SENDER = "xxxxx@qq.com"

三、flask-wtf实现表单验证(以用户注册的表单为例)

1、安装

bash
pip install flask-wtf

2、新建forms.py文件(表单验证器)

python
import wtforms
from wtforms.validators import Email as wt_Eamil,Length,EqualTo
from models import  UserModel,CaptchaEmail
from exts import  db

class ResisterForm(wtforms.Form):
    email=wtforms.StringField(validators=[wt_Eamil(message="邮箱格式错误!")])
    captcha=wtforms.StringField(validators=[Length(min=6,max=6,message="验证码格式错误")])
    username=wtforms.StringField(validators=[Length(min=3,max=20,message="用户名格式错误")])
    password=wtforms.StringField(validators=[Length(min=6,max=16,message="密码格式错误")])
    password_comfirm=wtforms.StringField(validators=[EqualTo("password",message="俩次密码不一致")])

3、实现验证邮箱

python
# 验证邮箱:邮箱存在抛出错误
def validate_email(self,field):
    email=field.data;
    user=UserModel.query.filter_by(email=email).first()
    if user:
       raise wtforms.ValidationError(message="该邮箱已经被注册")

4、实现验证码是否正确

python
 # 验证验证码是否正确
def validate_captcha(self,field):
    captcha=field.data
    email=self.email.data
    # 数据库存在邮箱一样,验证码一样的就认为验证码正确,验证通过后会清除记录
    captcha_email=CaptchaEmail.query.filter_by(email=email,captcha=captcha).first()
    if not captcha_email:
        raise wtforms.ValidationError(message="邮箱或验证码错误")
    # 验证通过,就删除记录
    db.session.delete(captcha_email)
    db.session.commit()

注意:flask的前端页面传递表单值时,需要给input标签加上name属性,并与flask后端表单验证器的字段名保持一致

5、注册用户(密码加密)

python
from werkzeug.security import generate_password_hash

@blueprint.route("/register", methods=["GET", "POST"])
def auth_register():
    if request.method == "GET":
        return render_template("register.html")
    else:
        # 表单校验器
        form = ResisterForm(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.auth_login"))
        else:
            print(form.errors)
            return redirect(url_for("auth.auth_register"))

6、加密密码和初始密码对比

python.................................
from werkzeug.security import check_password_hash

check_password_hash(user.password,password)

四、Hook钩子函数(类似拦截器)

python
@app.before_request
def my_before_request():
    user_id=session.get("user_id")
    if user_id:
        user=UserModel.query.get(user_id)
        # 设置全局属性, g是全局的
        setattr(g,"user",user)
    else:
        setattr(g,"user",None)

# 上下文处理器,它将一个名为 user 的变量添加到每个模板的上下文中
@app.context_processor
def my_context_processor():
    return {"user":g.user}

五、装饰器(权限验证)

decorators.py

python
from functools import wraps
from flask import g,redirect,url_for


def login_required(func):
    @wraps(func)
    # fun(a,b,c)
    # fun(1,2,c=3)
    def inner(*arg,**kwargs):
        if g.user:
            return func(*arg,**kwargs)
        else:
            return redirect(url_for("auth.auth_login"))

    return inner

注意

  • flask引入静态文件,却没有效果,可以使用Ctrl + Shift + Delete来清除浏览器缓存,在config配置SEND_FILE_MAX_AGE_DEFAULT=timedelta(seconds=1)