flask项目反思

Flask剖析

web框架与WSGI协议

img

Web服务器网关接口Python Web Server Gateway Interface,缩写为WSGI)

python语言定义的Web服务器Web应用程序框架之间的一种简单而通用的接口

jinja2 & Werkzeug
  • jinja2一个功能齐全的模板引擎

  • Werkzeug是一个WSGI工具包,它可以作为web框架的底层库

三者关系

Werkzeug用于接收http请求并对请求进行预处理,然后触发Flask框架,开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户,如果要返回给用户复杂的内容时,需要借助jinja2模板来实现对模板的处理。将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器。

flask项目

flask项目框架
/项目文件夹
    /models
    /static
    /templates
    app.py
数据库的连接

Mysql连接

  1. 配置数据库

# 数据库配置信息 
DB_USERNAME = 'root' #数据库系统账号
DB_PASSWORD = 'root' #数据库系统密码
DB_HOST = 'localhost'
DB_PORT = 3306  #数据库系统端口号
DB_NAME = 'forum' #数据库名称
​
# 数据库连接URI
DB_URI = f'mysql+pymysql://{DB_USERNAME}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}?charset=utf8'
​
# SQLAlchemy配置
SQLALCHEMY_DATABASE_URI = DB_URI
SQLALCHEMY_TRACK_MODIFICATIONS = False  # 关闭对模型修改的监控

2.数据库初始化

from flask_sqlalchemy import SQLAlchemy
db = SQLALchemy()
db.init_app(app) 

创建两个py文件(config.py ,exts.py)分别存放配置信息和组件初始化

在app.py中引入配置文件和组件初始化,将两者绑定

#导入文件
import config
from exts import db
​
app.config.from_object(config)  # 加载配置
#绑定信息
db.init_app(app)  # 初始化数据库

3.数据库模型定义

class Model(db.Model):#Model是自己定义的表单模型
    __table__ = 'demo' #给表单指定名称
     #属性信息
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(50), nullable=False)

在models文件夹中创建单独的py文件,存放一类的数据库模板

from exts import db
​
​
class Model(db.Model):#Model是自己定义的表单模型
    __table__ = 'demo' #给表单指定名称
  #属性信息
 id = db.Column(db.Integer, primary_key=True)
 name = db.Column(db.String(50), nullable=False)
前后端连接

1.通过render_template返回 html 模板

2.通过返回API接口

@bp.route('/login', methods=['GET', 'POST'])  #定义路由地址
def login():
    if request.method == 'GET':
        #返回html模板 --前后端不分离
        return render_template("front/login.html")
    else:
        #通过表单验证数据
        form = LoginForm(request.form)
        if form.validate():
            email = form.email.data
            password = form.password.data
            remember = form.remember.data
            user = UserModel.query.filter_by(email=email).first()
            if not user:
                return restful.params_error("邮箱或密码错误!")
            if not user.check_password(password):
                return restful.params_error("邮箱或密码错误!")
            session['user_id'] = user.id
            permissions = []
            if user.is_staff:
                token =create_access_token(identity=user.id)
                for attr in dir(Permission):
                    if not attr.startswith("_"):
                        permission = getattr(Permission, attr)
                        if user.has_permission(permission):
                            permissions.append(attr.lower())
            if remember == 1:
                session.permanent = True
            user = user.to_dict()
            user['permissions'] = permissions
            #API接口
            return restful.ok(data={"token": token, "user": user})
        else:
            return restful.params_error(message=form.messages[0])
获取HTTP数据
  1. 通过 request.args.get 获取查询参数:

    board_id = request.args.get("bd", type=int, default=None)
    • 来源: 查询参数(Query Parameters),即 URL 中 ? 后面的部分,例如 http://example.com/path?bd=123

    • 用途: 通常用于获取 URL 中的参数,这些参数是可选的,并且可以用于过滤、分页等操作。

    • 参数:

      • "bd":查询参数的键名。

      • type=int:将获取到的值转换为整数类型。

      • default=None:如果查询参数不存在,则返回默认值 None

  2. 通过 request.form 获取表单数据:

    form = RegisterForm(request.form)
    • 来源: 表单数据(Form Data),即通过 POST 请求提交的表单数据。

    • 用途: 通常用于处理用户提交的表单数据,例如注册表单、登录表单等。

    • 参数:

      • request.form:包含表单数据的字典对象。

      • RegisterForm:一个表单类,用于验证和处理表单数据。

总结:

  • request.args.get 用于从 URL 查询参数中获取数据,适用于 GET 请求。

  • request.form 用于从 POST 请求的表单数据中获取数据,适用于 POST 请求。

获取数据方法分类
  1. 获取查询参数(Query Parameters):

    from flask import request
    ​
    @app.route('/example')
    def example():
        param = request.args.get('key', default=None, type=str)
        return f'Query parameter: {param}'
  2. 获取表单数据(Form Data):

    from flask import request
    ​
    @app.route('/submit', methods=['POST'])
    def submit():
        form_data = request.form['key']
        return f'Form data: {form_data}'
  3. 获取 JSON 数据(JSON Data):

    from flask import request
    
    @app.route('/json', methods=['POST'])
    def json_endpoint():
        json_data = request.get_json()
        return f'JSON data: {json_data}'
  4. 获取文件上传(File Uploads):

    from flask import request
    
    @app.route('/upload', methods=['POST'])
    def upload_file():
        file = request.files['file']
        file.save('/path/to/save/file.ext')
        return 'File uploaded successfully'
  5. 获取请求头(Request Headers):

    from flask import request
    
    @app.route('/headers')
    def headers():
        user_agent = request.headers.get('User-Agent')
        return f'User-Agent: {user_agent}'
  6. 获取路径参数(Path Parameters):

    from flask import request
    
    @app.route('/user/<int:user_id>')
    def user_detail(user_id):
        return f'User ID: {user_id}'
  7. 获取 Cookie 数据:

    from flask import request
    
    @app.route('/cookie')
    def cookie():
        cookie_value = request.cookies.get('cookie_name')
        return f'Cookie value: {cookie_value}'
  8. 获取请求方法(Request Method):

    from flask import request
    
    @app.route('/method', methods=['GET', 'POST'])
    def method():
        method = request.method
        return f'Request method: {method}'
保存图片封装函数模板
def update_media(_path):
    form = UploadForm(request.files)
    if form.validate():
        image = form.image.data
        filename = image.filename
        # xxx.png,xx.jpeg
        _, ext = os.path.splitext(filename)
        filename = md5((g.user.email + str(time.time())).encode("utf-8")).hexdigest() + ext
	image_path = os.path.join(current_app.config[_path], filename)
	image.save(image_path)
   else:
        message = form.messages[0]
        return restful.params_error(message=message)
组件
flask_wtf
from werkzeug import secure_filename
#secure_filename 是一个用于安全处理文件名的函数
'''
secure_filename 函数会做以下几件事:
1.去除路径分隔符:如 / 和 \。
2.去除文件名中的控制字符:这些字符可能会被操作系统解释为特殊命令。
3.确保文件名是有效的:比如在 Windows 上,某些特定的文件名是不允许的(如 CON, PRN, AUX 等)。
'''
filename = secure_filename("/path/to/file.txt")
print(filename)  # 输出 "file.txt"

FileAllowed 可与 Flask-Uploads 协同工作,例如:

from flask.ext.uploads import UploadSet, IMAGES
from flask_wtf import Form
from flask_wtf.file import FileField, FileAllowed, FileRequired

images = UploadSet('images', IMAGES)

class UploadForm(Form):
    upload = FileField('image', validators=[
        FileRequired(),
        FileAllowed(images, 'Images only!')
    ])

它也可以在没有 Flask-Uploads 的情况下工作。你需要向 FileAllowed 传递扩展名:

class UploadForm(Form):
    upload = FileField('image', validators=[
        FileRequired(),
        FileAllowed(['jpg', 'png'], 'Images only!')
    ])

要对所有视图函数启用 CSRF 保护,你需要启用 CsrfProtect 模块:

from flask_wtf.csrf import CsrfProtect

CsrfProtect(app)

需要为 CSRF 指定一个密钥。通常,这与你的 Flask 应用 SECRET_KEY 一致。

flask_mail
MAIL_SERVER = 'smtp.qq.com'
MAIL_PORT = 587
MAIL_USE_TLS = True
'''
MAIL_PORT = 465
MAIL_USE_SSL = True
'''
MAIL_USERNAME = '2407992583@qq.com'
MAIL_PASSWORD = #
MAIL_DEFAULT_SENDER = #

TLS 163邮箱验证失败;qq邮箱验证成功

def email_captcha():
    # /email/captcha?email=xx@xx.com
    email = request.args.get("email")
    if not email:
        return restful.params_error(message="请先传入邮箱!")
    source = list(string.digits)
    captcha = "".join(random.sample(source, 6))
    subject = "【知识论坛】注册验证码"
    body = f"【知识论坛】您的注册验证码为{captcha}"
    # Celery 将 send_mail 任务添加到任务队列中,并传递相应的参数。
    current_app.celery.send_task("send_mail", (email, subject, body))
    #将数据存储到缓存中
    cache.set(email, captcha)
    return restful.ok(message="邮件发送成功!")

通过redis 缓存提高邮件发送效率

'''
 Celery的redis配置
'''
CELERY_BROKER_URL = "redis://localhost:6379/0"
CELERY_RESULT_BACKEND = "redis://localhost:6379/0"

'''
 Flask-Caching 的配置
'''
CACHE_TYPE = 'RedisCache'
CACHE_DEFAULT_TIMEOUT = 300
CACHE_REDIS_HOST = '127.0.0.1'
CACHE_REDIS_PORT = 6379
  • 21
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值