zoukankan      html  css  js  c++  java
  • 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)
  • 相关阅读:
    21.Merge Two Sorted Lists 、23. Merge k Sorted Lists
    34. Find First and Last Position of Element in Sorted Array
    leetcode 20. Valid Parentheses 、32. Longest Valid Parentheses 、301. Remove Invalid Parentheses
    31. Next Permutation
    17. Letter Combinations of a Phone Number
    android 常见分辨率(mdpi、hdpi 、xhdpi、xxhdpi )及屏幕适配注意事项
    oc 异常处理
    oc 类型判断
    oc Delegate
    oc 协议
  • 原文地址:https://www.cnblogs.com/louyifei0824/p/9774964.html
Copyright © 2011-2022 走看看