• Flask框架整理


    Flask基础部分

    Flask目录结构(蓝图)

    views中存放蓝图,每个蓝图也可以有自己的模板,用蓝图对不同功能的视图函数进行隔离,类似于django中的app

    pro_flask包的init.py文件, 用于注册所有的蓝图

    from flask import Flask
    from pro_flask.views.user import user
    from pro_flask.views.blog import blog
    
    
    app = Flask(__name__, template_folder='templates')
    app.register_blueprint(user)
    app.register_blueprint(blog)
    app.secret_key = "alex"

    manage.py文件,作为整个项目的启动文件

    from pro_flask import app
    from flask_script import Manager
    from flask_bootstrap import Bootstrap
    
    
    Bootstrap(app)
    manage = Manager(app)
    if __name__ == '__main__':
        # app.__call__()
        manage.run()

    views包中的blog.py,必须要通过session验证才能访问,否则回到登录界面

    from flask import Blueprint, session, redirect, url_for, render_template
    
    blog = Blueprint("blog", __name__, template_folder='templates')
    
    
    @blog.route("/index/")
    def index():
        return render_template("index.html")
    
    
    @blog.before_request # 请求该蓝图中所有的函数时都会先走这儿!
    def process_request():
        val = session.get("login")
        if val:
            return None 
        else:
            return redirect(url_for("user.login")) # 如果没有session则阻断请求

    views包中的user.py,定义一些与用户相关的视图函数

    from flask import Blueprint, render_template, request, session, url_for, redirect
    from flask_wtf import FlaskForm
    from wtforms import StringField, PasswordField, SubmitField
    from wtforms.validators import DataRequired, EqualTo, Length, ValidationError
    
    user = Blueprint("user", __name__, template_folder='templates')
    
    
    @user.route("/login/", methods=["GET", "POST"])
    def login():
        if request.method == "POST":
            username = request.form.get("username")
            password = request.form.get("password")
            if username == "alex" and password == "123":
                session["name"] = "alex"
                session["password"] = "123"
                session["login"] = 1
                return redirect(url_for("blog.index"))
        return render_template("login.html")
    
    
    @user.route("/logout/")
    def logout():
        session.pop("login")
        return render_template("base.html")
    
    
    class Register(FlaskForm):
      # username为表单中input中name属性对应的值, "用户名"为label的内容, balidators为验证器(写一些验证表单内容的规则) username
    = StringField("用户名", validators=[DataRequired("用户名不能为空"), # 表单的验证器 Length(min=6, max=12, message="长度需要在6~12个字符之间")]) password = PasswordField("密码", validators=[DataRequired("密码不能为空"), Length(min=6, max=12, message="密码长度需要在6~12个字符之间")]) confirm = PasswordField("确认密码", validators=[DataRequired("密码不能为空"), EqualTo("password", message="两次输入的密码不一致")]) submit = SubmitField("注册") def validate_username(self, field): if self.username.data == "alex": raise ValidationError("该用户已存在") @user.route("/register/", methods=["GET", "POST"]) def register(): form = Register() if form.validate_on_submit(): return redirect(url_for("user.login")) return render_template("register.html", form=form)

    加载静态资源的方法

    {{ url_for('static',filename='路径/文件名称.css/js/jpg') }}

    实例:

    {% block metas %}
        {{ super() }}
        <link rel="icon" href="{{ url_for('static',filename='img/1.jpeg',_external=True) }}">
    {% endblock %}

    Flask原码部分理解

    app.run()方法,负责启动项目,监听请求,那么它在内部做了哪些操作呢???

    def run(self):
        ...
       from werkzeug.serving import run_simple
       run_simple(host, port, self, **options) # 第三个参数self指的是app这个对象自己
       ...

    以上是原码中app的run方法的部分内容,其实它执行的是run_simple这个方法

    第三个参数将被反射调用,那么app(),就是去执行了app.__call__()方法

    可以看出__call__方法其实是在调用wsgi_app这个接口

    那么也就是说,将请求相关的所有内容都封装到了一个类的对象中

    ctx = self.request_context(environ) # 此时的ctx就是请求的对象

    跟进_request_ctx_stack

    可以看出将那个请求对象push进了这个LocalStack类的对象里,跟进到LocalStack()中

    找到这个push方法,这里的obj就是那个请求的对象

     _local是在类初始化时,实例化的Local对象,反射这个Local对象中是否有stack这个属性或方法,如果没有,则执行_local.stack = [], rv = []

    在rv列表中把那个请求对象加进来,而_local.stack = [],会触发Local里面的__setattr__方法,所以跟进到Local中查看,Local的实现原理类似于threading.Local

    
    
    try:
    from greenlet import getcurrent as get_ident # 如果有协程库,那么就支持协程
    except ImportError:
    try:
    from thread import get_ident
    except ImportError:
    from _thread import get_ident # 支持线程
    class Local(object):
        __slots__ = ('__storage__', '__ident_func__')
    
        def __init__(self):
            object.__setattr__(self, '__storage__', {})  # 使用这种方法不会触发下面的__setattr__方法,避免递归
            object.__setattr__(self, '__ident_func__', get_ident)# 将获取唯一协程标识的方法赋值给了__ident_func__
       def __getattr__(self, name):
            try:
                return self.__storage__[self.__ident_func__()][name]
            except KeyError:
                raise AttributeError(name)
    
        def __setattr__(self, name, value):
            ident = self.__ident_func__()
            storage = self.__storage__
            try:
                storage[ident][name] = value # 为每个协程/线程开辟空间,如果未开辟 则执行下面的代码
            except KeyError:
                storage[ident] = {name: value}
    
        def __delattr__(self, name):
            try:
                del self.__storage__[self.__ident_func__()][name]
            except KeyError:
                raise AttributeError(name)
  • 相关阅读:
    vs 编译加速
    leetcode 1405
    sort 从大到小从小到大
    leetcode1404
    leetcode 1406
    leetcode 1556
    杭电研究生自动登录联网脚本
    Cannot mix incompatible Qt library (version ) with this library (version ) 解决方案
    目标检测算法优化技巧
    特征工程和模型融合--机器学习--思维导图和笔记
  • 原文地址:https://www.cnblogs.com/louyifei0824/p/9774964.html
Copyright © 2020-2023  润新知