views中存放蓝图,每一个蓝图也能够有本身的模板,用蓝图对不一样功能的视图函数进行隔离,相似于django中的appcss
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"
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()
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则阻断请求
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') }}
实例:html
{% block metas %} {{ super() }} <link rel="icon" href="{{ url_for('static',filename='img/1.jpeg',_external=True) }}"> {% endblock %}
def run(self): ...
from werkzeug.serving import run_simple
run_simple(host, port, self, **options) # 第三个参数self指的是app这个对象本身
...
以上是原码中app的run方法的部份内容,其实它执行的是run_simple这个方法django
第三个参数将被反射调用,那么app(),就是去执行了app.__call__()方法flask
能够看出__call__方法实际上是在调用wsgi_app这个接口bootstrap
那么也就是说,将请求相关的全部内容都封装到了一个类的对象中session
ctx = self.request_context(environ) # 此时的ctx就是请求的对象
跟进_request_ctx_stackapp
能够看出将那个请求对象push进了这个LocalStack类的对象里,跟进到LocalStack()中ide
找到这个push方法,这里的obj就是那个请求的对象函数
_local是在类初始化时,实例化的Local对象,反射这个Local对象中是否有stack这个属性或方法,若是没有,则执行_local.stack = [], rv = []ui
在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)