1. 程式人生 > >Flask10 登錄模塊、表單框架、表單渲染、表單驗證、bookie、請求之前鉤子、g對象、編寫裝飾器

Flask10 登錄模塊、表單框架、表單渲染、表單驗證、bookie、請求之前鉤子、g對象、編寫裝飾器

data 函數實現 https tid 路徑 錯誤 post請求 字符 als

技術分享
from flask import Flask
from flask import request
from flask import render_template
from flask_wtf import CSRFProtect as WTF # 利用表單類去渲染模板時需要用到

from forms import LoginForm

app = Flask(__name__)
WTF(app) # 在app上註冊一個 WTF (所有的flask插件都必須進行註冊)
app.config.from_pyfile(config.py) # 修改app的配置文件(使 WTF_CSRF_ENABLED 失效)
@app.route(/) def index(): return render_template(index.html) @app.route(/login/, methods=[GET, POST]) def login(): if request.method == GET: print(GET請求) liginForm = LoginForm() # 相當於java中利用無參構造器創建對象 return render_template(login.html, loginForm = liginForm)
if request.method == POST: print(POST請求) loginForm = LoginForm(request.form) # 相當於java中利用有參構造器創建對象 print(loginForm) email = loginForm.email.data password = loginForm.password.data print("郵箱為:{},密碼為:{}".format(email, password)) if loginForm.validate():
return render_template(index.html) else: return 表單驗證失敗,錯誤信息 -> + str(loginForm.errors) print(app.url_map) if __name__ == __main__: app.run(debug=True)
python代碼

1 一個請求路徑怎麽實現兩個邏輯功能

  實例:登錄模塊

  進入登錄頁面和點擊登錄的請求路徑都是一樣的,只不過他們的請求方式不一樣而已;這樣我們在後臺就只需要寫一個視圖函數來實現兩個功能邏輯;進入登錄頁面的請求時GET請求,點擊登錄的請求是POST請求

2 後臺如何利用一個視圖函數實現不同的邏輯

  根據請求方式不同執行不同的邏輯

  利用 request 對象的屬性來判斷請求方式

    request.method    返回值時請求方式(GET/POST/HEAD/OPTIONS)

  2.1 編寫一個簡單的登錄模塊

    2.1.1 要求

      去往登錄頁面和點擊登錄的路徑保持一致

      後臺利用一個視圖函數處理去往登錄頁面和點擊登錄按鈕的請求

      如果是去往登錄頁面的請求就響應一個登錄頁面,如果是點擊登錄頁面的請求就響應一個主頁面並獲取相關的登錄數據

    2.1.2 編寫連個HTML文件

技術分享
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>主頁面</title>
</head>
<body>
    <h2>庠序科技主頁面</h2>
    <hr />
    <h4>Donot aim for your success if you really want it. Just stick to do what you love and believe in.</h4>
</body>
</html>
index.html 技術分享
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登錄頁面</title>
</head>
<body>
    <h2>庠序科技登錄頁面</h2>
    <hr />
    <div>
        <form action="/login/" method="post">
            <div>
                <label for="email">郵箱:</label><input type="text" id="email" name="email" />
            </div>
            <div>
                <label for="password">密碼:</label><input type="password" id="password" name="password" />
            </div>
            <div>
                <button type="submit">登錄</button>
            </div>
        </form>
    </div>
</body>
</html>
login.html

    2.1.3 編寫視圖函數

技術分享

技術分享
from flask import Flask
from flask import request
from flask import render_template

from werkzeug.datastructures import ImmutableMultiDict

app = Flask(__name__)


@app.route(/)
def index():
    return render_template(index.html)

@app.route(/login/, methods=[GET, POST])
def login():
    if request.method == GET:
        print(GET請求)
        return render_template(login.html)
    if request.method == POST:
        print(POST請求)
        formData = request.form
        print(type(formData))
        print(formData)
        email = formData.get(email, null)
        password = formData[password]
        print("郵箱數據為:{},密碼數據為:{}".format_map(email, password))

        return render_template(index.html)

print(app.url_map)


if __name__ == __main__:
    app.run(debug=True)
app.py

3 利用表單框架書寫表單

  3.1 導入表單框架

    pip3 install -i https://pypi.doubanio.com/simple/ flask-wtf

  3.2 編寫表單類

技術分享
from flask_wtf import FlaskForm
from wtforms import Form
from wtforms import StringField, BooleanField

class LoginForm(Form):
    email = StringField()
    password = StringField()

loginForm = LoginForm() # 實例化一個LoginForm對象
print(loginForm.password.label) 
print(loginForm.email.label)
print(loginForm.email())
print(loginForm.data)
print(loginForm.errors)
測試form框架

技術分享

  3.3 利用表單類去渲染模板

    3.3.1 準備

      從 flask_wtf 中導入 CSRFProtect    

        from flask_wtf import CSRFProtect as WTF       # 利用表單類去渲染模板時需要用到

      在 Flask對象 上註冊一個 CSRFProtect

        WTF(app) # 在app上註冊一個 WTF (所有的flask插件都必須進行註冊)

      修改 Flask對象 的配置文件使得 WTF_CSRF_ENABLED 失效

        app.config.from_pyfile(‘config.py‘) # 修改app的配置文件(使 WTF_CSRF_ENABLED 失效)

        config.py 文件中的信息為  WTF_CSRF_ENABLED = False

          詳情請查看修改 Flask應用默認配置 先關內容

    3.3.2 利用表單類渲染模板的步驟

      》導入表單類

        from forms import LoginForm

      》創建一個表單類對象

        liginForm = LoginForm()

      》將這個表單對象傳到模板中去

        render_template(‘login.html‘, loginForm = liginForm)

      》利用表單對象的相關方法去渲染模板

        {{ loginForm.email.label }}:{{ loginForm.email() }}

          註意:loginForm.email.label 和 loginForm.email() 都是python表達式,他們的返回值是一個字符串

技術分享
from flask import Flask
from flask import request
from flask import render_template
from flask_wtf import CSRFProtect as WTF # 利用表單類去渲染模板時需要用到

from forms import LoginForm

app = Flask(__name__)
WTF(app) # 在app上註冊一個 WTF (所有的flask插件都必須進行註冊)
app.config.from_pyfile(config.py) # 修改app的配置文件(使 WTF_CSRF_ENABLED 失效)


@app.route(/)
def index():
    return render_template(index.html)

@app.route(/login/, methods=[GET, POST])
def login():
    if request.method == GET:
        print(GET請求)
        liginForm = LoginForm()
        return render_template(login.html, loginForm = liginForm)

print(app.url_map)


if __name__ == __main__:
    app.run(debug=True)
python代碼 技術分享
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登錄頁面</title>
</head>
<body>
    <h2>庠序科技登錄頁面</h2>
    <hr />
    <div>
        <form action="/login/" method="post">
            <div>
                {{ loginForm.email.label }}:{{ loginForm.email() }}
            </div>
            <div>
               {{ loginForm.password.label }}:{{ loginForm.password() }}
            </div>
            <div>
                <button type="submit">登錄</button>
            </div>
        </form>
    </div>
</body>
</html>
模板代碼

技術分享

  3.4 利用表單類獲取數據

技術分享
from flask import Flask
from flask import request
from flask import render_template
from flask_wtf import CSRFProtect as WTF # 利用表單類去渲染模板時需要用到

from forms import LoginForm

app = Flask(__name__)
WTF(app) # 在app上註冊一個 WTF (所有的flask插件都必須進行註冊)
app.config.from_pyfile(config.py) # 修改app的配置文件(使 WTF_CSRF_ENABLED 失效)


@app.route(/)
def index():
    return render_template(index.html)

@app.route(/login/, methods=[GET, POST])
def login():
    if request.method == GET:
        print(GET請求)
        liginForm = LoginForm() # 相當於java中利用無參構造器創建對象
        return render_template(login.html, loginForm = liginForm)
    if request.method == POST:
        print(POST請求)
        loginForm = LoginForm(request.form)  # 相當於java中利用有參構造器創建對象
        print(loginForm)
        email = loginForm.email.data
        password = loginForm.password.data
        print("郵箱為:{},密碼為:{}".format(email, password))
        return render_template(index.html)

print(app.url_map)


if __name__ == __main__:
    app.run(debug=True)
View Code

  3.5 如何利用表單框架去驗證獲取到的表單數據格式

    3.5.1 在表單中為每個字段定義驗證器

技術分享
from flask_wtf import FlaskForm
from wtforms import Form
from wtforms import StringField, BooleanField # 導入用到的字段
from wtforms.validators import InputRequired, Length, Email # 導入用到的驗證器

class LoginForm(FlaskForm): # 註意如果單獨使用功能時要繼承Form,如果在Flask框架中使用是要繼承FlaskForm
    email = StringField(
        label=郵箱, # 修改渲染時的value值
        validators=[ # 設定字段驗證器
            InputRequired(郵箱是必填項),
            Email(郵箱格式錯誤)
        ]
    )
    password = StringField(
        label=密碼,
        validators=[
            InputRequired(密碼為必填項),
            Length(6, 9, 密碼長度為6到9)
        ]
    )

# loginForm = LoginForm() # 實例化一個LoginForm對象
# print(loginForm.password.label)
# print(loginForm.email.label)
# print(loginForm.email())
# print(loginForm.data)
# print(loginForm.errors)
表單類

    3.5.2 在視圖函數中利用表單對象去驗證表單對象中的數據是否有效

   技術分享

  3.6 如何驗證表單數據的合法性

    前提:已經從前端獲取到用戶數據的郵箱和密碼數據

    思路:利用郵箱到數據庫查詢用戶信息,如果有先關數據說明郵箱數據有效;通過郵箱查詢到的用戶信息中的密碼數據和前端傳過來的密碼數據進行比較,如果相等就說明密碼數據有效

    3.6.1 模擬一個數據模型來充當數據庫

技術分享
class User: # 模擬用戶類
    def __init__(self, id, email, password, name):
        self.id = id
        self.email = email
        self.password = password
        self.name = name

    def check_password(self, password):
        return self.password == password

users = [ # 模擬用戶數據
    User(1, [email protected], 111111, fury),
    User(2, [email protected], 222222, zeus),
    User(3, [email protected], 333333, warrior)
]

# 根據用戶ID去獲取數據
def findById(userId):
    for user in users:
        if user.id == userId:
            return user
    else:
        return None

# 根據用戶郵箱去獲取數據
def findByEmail(email):
    for user in users:
        if user.email == email:
            return user
    else:
        return None
View Code

    3.6.2 調用相關方法判斷表單數據是否有效

  技術分享

技術分享
from flask import Flask
from flask import request
from flask import render_template
from flask_wtf import CSRFProtect as WTF # 利用表單類去渲染模板時需要用到

from forms import LoginForm

from models import findByEmail, findById

app = Flask(__name__)
WTF(app) # 在app上註冊一個 WTF (所有的flask插件都必須進行註冊)
app.config.from_pyfile(config.py) # 修改app的配置文件(使 WTF_CSRF_ENABLED 失效)


@app.route(/)
def index():
    return render_template(index.html)

@app.route(/login/, methods=[GET, POST])
def login():
    if request.method == GET:
        print(GET請求)
        liginForm = LoginForm() # 相當於java中利用無參構造器創建對象
        return render_template(login.html, loginForm = liginForm)
    if request.method == POST:
        print(POST請求)
        loginForm = LoginForm(request.form)  # 相當於java中利用有參構造器創建對象
        print(loginForm)
        if loginForm.validate():
            email = loginForm.email.data
            password = loginForm.password.data
            print("郵箱為:{},密碼為:{}".format(email, password))
            user = findByEmail(email)
            if user:
                if user.check_password(password):
                    return render_template(index.html)
                else:
                    return 密碼錯誤
            else:
                return 該郵箱為註冊

        else:
            return 表單驗證失敗,錯誤信息 ->  + str(loginForm.errors)

print(app.url_map)


if __name__ == __main__:
    app.run(debug=True)
View Code

  3.7 如何實現在用戶登錄成功後進入主頁面,並顯示:歡迎XXX

    如果從前端獲取到的登錄數據判斷為有效後,就將用戶的名字信息添加到主頁模板中,並渲染主頁模板;如果用戶沒有登錄就進入到主頁面時會有登錄和註冊兩個按鈕

    技術分享

技術分享

  3.8 如何實現當用戶成功登錄並進入主頁後,當客戶端下次再次訪問這也的時候服務器會知道該前端之前已經登錄過

    思路:用戶數據驗證成功後,就將唯一識別用戶的信息存儲到客戶端的cookie中,當客戶端下次訪問服務器時機會攜帶這個cookie信息,服務器會根據這個cookie信息去判斷該客戶端是否登陸過,如果登陸過就進入主頁顯示“歡迎xxx”,否則就進入主頁提示用戶登錄

    註意:可以根據用戶是否選擇來“記住我”來設置cookie的有效時間

    3.8.1 數據驗證成功後就設置cookie

      技術分享

    3.8.2 用戶進入主頁時會利用請求對象去獲取cookie數據,如果獲取到了就會在進入主頁後顯示為登錄狀態

      技術分享

      註意:這裏登錄成功後僅僅會提示登錄成功,並不會重定向到主頁面去(故:需要手動修改路徑才能到主頁面去,這裏有待改進)

  3.9 這麽把請求之前的邏輯單獨羅列出來

    思路:利用請求之前那個鉤子 @app.before_request 這個鉤子註釋的函數會在每個請求之前執行

      技術分享

  3.10 g對象的妙用

    每個請求對象都會有一個g對象,可以向g對象添加屬性,而且這g對象在這個請求路徑下的所有函數共享這個g對象

  3.11 如果用戶在沒有登錄的情況下進入到主頁面後怎麽強制返回到登錄頁面

    思路:寫一個裝飾器,該裝飾器的功能是,如果進入主頁面時通過cookie數據能夠獲取到用戶數據就什麽也不做,如果獲取不到就重定向到登錄頁面

  技術分享

4 項目信息

  4.1 項目結構

    技術分享

  4.2 項目源代碼

    點擊前往

    

      

Flask10 登錄模塊、表單框架、表單渲染、表單驗證、bookie、請求之前鉤子、g對象、編寫裝飾器