首页 > 其他 > 详细

Flask框架整理及配置文件

时间:2019-12-05 19:46:01      阅读:246      评论:0      收藏:0      [点我收藏+]

 


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)
技术分享图片

 

 


配置文件的参数

flask中的配置文件是一个flask.config.Config对象(继承字典),默认配置为:

技术分享图片
{
DEBUG: get_debug_flag(default=False), 是否开启Debug模式
TESTING: False, 是否开启测试模式
PROPAGATE_EXCEPTIONS: None, 
PRESERVE_CONTEXT_ON_EXCEPTION: None,
SECRET_KEY: None,
PERMANENT_SESSION_LIFETIME: timedelta(days=31),
USE_X_SENDFILE: False,
LOGGER_NAME: None,
LOGGER_HANDLER_POLICY: always,
SERVER_NAME: None,
APPLICATION_ROOT: None,
SESSION_COOKIE_NAME: session,
SESSION_COOKIE_DOMAIN: None,
SESSION_COOKIE_PATH: None,
SESSION_COOKIE_HTTPONLY: True,
SESSION_COOKIE_SECURE: False,
SESSION_REFRESH_EACH_REQUEST: True,
MAX_CONTENT_LENGTH: None,
SEND_FILE_MAX_AGE_DEFAULT: timedelta(hours=12),
TRAP_BAD_REQUEST_ERRORS: False,
TRAP_HTTP_EXCEPTIONS: False,
EXPLAIN_TEMPLATE_LOADING: False,
PREFERRED_URL_SCHEME: http,
JSON_AS_ASCII: True,
JSON_SORT_KEYS: True,
JSONIFY_PRETTYPRINT_REGULAR: True,
JSONIFY_MIMETYPE: application/json,
TEMPLATES_AUTO_RELOAD: None,
}
技术分享图片

导入配置文件的几种策略

app.config[‘DEBUG‘] = True

PS: 由于Config对象本质上是字典,所以还可以使用app.config.update(...)

app.config.from_pyfile("python文件名称")
如:
settings.py/
DEBUG = True

app.config.from_pyfile("settings.py")

app.config.from_envvar("环境变量名称")

环境变量的值为python文件名称名称,内部调用from_pyfile方法

app.config.from_json("json文件名称")

JSON文件名称,必须是json格式,因为内部会执行json.loads

app.config.from_mapping({‘DEBUG‘:True})

字典格式

app.config.from_object("python类或类的路径")

技术分享图片
app.config.from_object(pro_flask.settings.TestingConfig)

settings.py/

class Config(object):
DEBUG = False
TESTING = False
DATABASE_URI = sqlite://:memory:

class ProductionConfig(Config):
DATABASE_URI = mysql://user@localhost/foo

class DevelopmentConfig(Config):
DEBUG = True

class TestingConfig(Config):
TESTING = True

PS: 从sys.path中已经存在路径开始写


PS: settings.py文件默认路径要放在程序root_path目录,如果instance_relative_config为True,则就是instance_path目录配置文件
技术分享图片

 

Flask框架整理及配置文件

原文:https://www.cnblogs.com/abdm-989/p/11991235.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!