Flask框架整理

Flask基礎部分

Flask目錄結構(藍圖)

views中存放藍圖,每一個藍圖也能夠有本身的模板,用藍圖對不一樣功能的視圖函數進行隔離,相似於django中的appcss

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') }}

實例:html

{% 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這個方法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)
相關文章
相關標籤/搜索