1. 程式人生 > >1.7 flask 的元件 wtfroms使用

1.7 flask 的元件 wtfroms使用

2019-1-7 17:59:37

還有兩天左右flask就結束啦!昨晚逛了一下吾愛破解還有慕課,發現有三個意外專案,

Django生鮮專案,flask電影網站專案,vue美團網專案,都儲存百度雲啦,寒假可以搞事情啦

還有十天左右的視訊,看完後認證整理部落格,然後爭取整理本書,到時候回學校列印,233333333!

想想都是很有成就感的一件事情!

越努力,越幸運!永遠不要高估自己!

 

今天講了wtfroms 元件,就是Django中的form  modelsForm 類似!

書上介紹的元件很多,flask那本書!

flask參考連結: https://www.cnblogs.com/wupeiqi/articles/8202357.html

 

還講了 重要的東西  localproxy

這是關於localproxy的一個demo

s1.py

# by luffycity.com

DATA = {
    'request':{
        'method':"GET",
        'form':{}
    },
    'session':{
        'user':'alex',
        'age':"19"
    }
}

class LocalProxy(object):
    def __init__(self,key):
        self.key 
= key def get_dict(self): return DATA[self.key] def __str__(self): return 'asdf' def __getattr__(self, item): data_dict = self.get_dict() return data_dict[item] def __getitem__(self, item): data_dict = self.get_dict() return data_dict[item]
def __add__(self, other): return other + 1 request = LocalProxy('request') session = LocalProxy('session')

s2.py

from s2 import request,session



print(request.method)
print(request.form)

print(session.user)
print(session.age)

這是在flask中實現上下文管理  resquest 和session 的方法

from flask import Flask,request,session

app = Flask(__name__)


@app.route('/index')
def index():
    # 1. request是LocalProxy物件
    # 2. 物件中有method、執行__getattr__
    print(request.method)
    # request['method']
    # request + 1

    # 1. session是LocalProxy物件
    # 2. LocalProxy物件的__setitem__
    session['x'] = 123

    return "Index"


if __name__ == '__main__':
    app.run()
    # app.__call__
    # app.wsgi_app

"""
第一階段:請求到來
    將request和Session相關資料封裝到ctx=RequestContext物件中。
    再通過LocalStack將ctx新增到Local中。
    __storage__ = {
        1231:{'stack':[ctx(request,session)]}
    }
第二階段:檢視函式中獲取request或session
    方式一:直接找LocalStack獲取
            from flask.globals import _request_ctx_stack
            print(_request_ctx_stack.top.request.method)
            
    方式二:通過代理LocalProxy(小東北)獲取
            from flask import Flask,request
            print(request.method)
            
"""

這是很重要的一張圖,搞懂這個圖就清楚 reqeust session  g 和app 的上下文管理用法啦

 

 

wtforms基本使用

貼上原始碼

from flask import Flask,request,render_template,session,current_app,g,redirect
from wtforms import Form
from wtforms.fields import simple
from wtforms.fields import html5
from wtforms.fields import core

from wtforms import widgets
from wtforms import validators

app = Flask(__name__)


class LoginForm(Form):
    name = simple.StringField(
        validators=[
            validators.DataRequired(message='使用者名稱不能為空.'),
            # validators.Length(min=6, max=18, message='使用者名稱長度必須大於%(min)d且小於%(max)d')
        ],
        widget=widgets.TextInput(),
        render_kw={'placeholder':'請輸入使用者名稱'}
    )
    pwd = simple.PasswordField(
        validators=[
            validators.DataRequired(message='密碼不能為空.'),
            # validators.Length(min=8, message='使用者名稱長度必須大於%(min)d'),
            # validators.Regexp(regex="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[[email protected]$!%*?&])[A-Za-z\[email protected]$!%*?&]{8,}",
            #                   message='密碼至少8個字元,至少1個大寫字母,1個小寫字母,1個數字和1個特殊字元')

        ],
        render_kw={'placeholder':'請輸入密碼'}
    )


@app.route('/login',methods=['GET','POST'])
def login():
    if request.method == "GET":
        form = LoginForm()
        # print(form.name,type(form.name)) # form.name是StringField()物件, StringField().__str__
        # print(form.pwd,type(form.pwd))   # form.pwd是PasswordField()物件,PasswordField().__str__
        return render_template('login.html',form=form)

    form = LoginForm(formdata=request.form)
    if form.validate():
        print(form.data)
        return redirect('https://www.luffycity.com/home')
    else:
        # print(form.errors)
        return render_template('login.html', form=form)


class RegisterForm(Form):
    name = simple.StringField(
        label='使用者名稱',
        validators=[
            validators.DataRequired()
        ],
        widget=widgets.TextInput(),
        render_kw={'class': 'form-control'},
        default='alex'
    )

    pwd = simple.PasswordField(
        label='密碼',
        validators=[
            validators.DataRequired(message='密碼不能為空.')
        ],
        widget=widgets.PasswordInput(),
        render_kw={'class': 'form-control'}
    )

    pwd_confirm = simple.PasswordField(
        label='重複密碼',
        validators=[
            validators.DataRequired(message='重複密碼不能為空.'),
            validators.EqualTo('pwd', message="兩次密碼輸入不一致")
        ],
        widget=widgets.PasswordInput(),
        render_kw={'class': 'form-control'}
    )

    email = html5.EmailField(
        label='郵箱',
        validators=[
            validators.DataRequired(message='郵箱不能為空.'),
            validators.Email(message='郵箱格式錯誤')
        ],
        widget=widgets.TextInput(input_type='email'),
        render_kw={'class': 'form-control'}
    )

    gender = core.RadioField(
        label='性別',
        choices=(
            (1, ''),
            (2, ''),
        ),
        coerce=int # int("1")
    )
    city = core.SelectField(
        label='城市',
        choices=(
            ('bj', '北京'),
            ('sh', '上海'),
        )
    )

    hobby = core.SelectMultipleField(
        label='愛好',
        choices=(
            (1, '籃球'),
            (2, '足球'),
        ),
        coerce=int
    )

    favor = core.SelectMultipleField(
        label='喜好',
        choices=(
            (1, '籃球'),
            (2, '足球'),
        ),
        widget=widgets.ListWidget(prefix_label=False),
        option_widget=widgets.CheckboxInput(),
        coerce=int,
        default=[1, ]
    )



@app.route('/register', methods=['GET', 'POST'])
def register():
    if request.method == 'GET':
        form = RegisterForm()
        return render_template('register.html', form=form)

    form = RegisterForm(formdata=request.form)
    if form.validate():
        print(form.data)
        return redirect('https://www.luffycity.com/home')

    return render_template('register.html', form=form)

import helper
class UserForm(Form):
    city = core.SelectField(
        label='城市',
        choices=(),
        coerce=int
    )
    name = simple.StringField(label='姓名')

    # 為了解決資料庫修改資訊未能在頁面重新整理,
    #  解決方法: 就是直接在檢視函式中先父類初始化和查詢一下該欄位的值
    def __init__(self,*args,**kwargs):
        super(UserForm,self).__init__(*args,**kwargs)

        self.city.choices=helper.fetch_all('select id,name from tb1',[],type=None)


@app.route('/user')
def user():
    if request.method == "GET":
        #form = UserForm(data={'name':'alex','city':3})
        form = UserForm()
        return render_template('user.html',form=form)


if __name__ == '__main__':
    app.run()

連線資料庫用的連線池

helper.py

import pymysql
from DBUtils.PooledDB import PooledDB, SharedDBConnection
import pymysql

POOL = PooledDB(
        creator=pymysql,  # 使用連結資料庫的模組
        maxconnections=6,  # 連線池允許的最大連線數,0和None表示不限制連線數
        mincached=2,  # 初始化時,連結池中至少建立的空閒的連結,0表示不建立
        maxcached=5,  # 連結池中最多閒置的連結,0和None不限制
        maxshared=3,
        # 連結池中最多共享的連結數量,0和None表示全部共享。PS: 無用,因為pymysql和MySQLdb等模組的 threadsafety都為1,所有值無論設定為多少,_maxcached永遠為0,所以永遠是所有連結都共享。
        blocking=True,  # 連線池中如果沒有可用連線後,是否阻塞等待。True,等待;False,不等待然後報錯
        maxusage=None,  # 一個連結最多被重複使用的次數,None表示無限制
        setsession=[],  # 開始會話前執行的命令列表。如:["set datestyle to ...", "set time zone ..."]
        ping=0,
        # ping MySQL服務端,檢查是否服務可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always
        host='127.0.0.1',
        port=3306,
        user='root',
        password='123456',
        database='s9day119',
        charset='utf8'
    )

def connect(type):
    conn = POOL.connection()
    cursor = conn.cursor(cursor=type)
    return conn,cursor


def connect_close(conn,cursor):
    cursor.close()
    conn.close()

def fetch_all(sql,args,type=pymysql.cursors.DictCursor):
    conn,cursor = connect(type)

    cursor.execute(sql, args)
    record_list = cursor.fetchall()
    connect_close(conn,cursor)

    return record_list


def fetch_one(sql, args):
    conn, cursor = connect()
    cursor.execute(sql, args)
    result = cursor.fetchone()
    connect_close(conn, cursor)

    return result


def insert(sql, args):
    conn, cursor = connect()
    row = cursor.execute(sql, args)
    conn.commit()
    connect_close(conn, cursor)
    return row

login.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
    <form method="post" novalidate>
        <p>使用者名稱:{{form.name}}  {{form.name.errors[0]}}</p>
        <p>密碼:{{form.pwd}}  {{form.pwd.errors[0]}} </p>
        <p><input type="submit" value="提交"  ></p>
    </form>
</body>
</html>

register.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
    <form method="post" novalidate>

        {% for field in form %}
        <p>{{field.label}}: {{field}}   {{field.errors[0]}}</p>
        {% endfor %}

        <input type="submit" value="提交">
    </form>
</body>
</html>

user.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
    <form method="post">
        {% for field in form %}
        <p>{{field.label}}: {{field}}   {{field.errors[0]}}</p>
        {% endfor %}
        <input type="submit" value="提交">
    </form>
</body>
</html>

貼上筆記:

s9day119 

內容回顧:
    第一部分:Flask
        1. 談談你對django和flask的認識?
        
        2. Flask基礎:
            - 配置檔案:反射+importlib
            - 路由系統:
                - 裝飾器 @app.route()
                - 引數:
                    - url
                    - endpoint
                    - methods
                - 加裝飾器
                    - endpoint預設是函式名
                    - functools.wraps(func)  + functools.partial
                - 寫路由兩種方式:
                    - 裝飾器
                    - add_url_rule
                - 自定義支援正則的URL
            - session 
            - 藍圖 
                - 目錄結構劃分
                - 字首
                - 特殊裝飾器
        3. 上下文管理 
            - threading.local
                - 為每個執行緒開闢空間,使得執行緒之間進行資料隔離。
                - 應用:DBUtils中為每個執行緒建立一個數據庫連線時使用。
            - 面向物件特殊方法:
                - getattr
                - setattr
                - delattr
            - 偏函式
            - 單例模式
            - 請求上下文流程:
                - 班級示例:
                - 原始碼流程:
                    - __call__
                    - wsgi_app
                        - ctx = RequestContext(): 封裝= 請求資料+空session
                        - ctx.push() : 將ctx傳給LocalStack物件,LocalStack再將資料傳給Local儲存起來。
                                       問題:Local中是如何儲存?
                                            __storage__ = {
                                                1231:{}
                                            }
                                        問題:LocalStack作用?
                                            __storage__ = {
                                                1231:{stack:[ctx] }
                                            }
                    - 檢視函式:再次去獲取
                - 關閉
        
        
        4. 第三方元件:
            1. flask-session 
            2. DBUtils 
    
    第二部分:資料庫&前端
        1. 什麼是響應式佈局?
            @media屬性
        2. MySQL資料庫
            - 引擎:
                - innodb
                    - 支援事務
                    -- 行鎖
                        - 表鎖
                        - 示例:
                            - 終端:
                                begin;
                                select xx from xx for update;
                                commit;
                            - pymysql
                                cursor.execute('select * from xx for update')
                            - django
                                with trancation.automic():
                                    models.User.objects.all().for_update()
                - mysaim
                    - 不支援事務
                    -- 表鎖 
                    - 快
                        
今日內容:
    1. 上下文管理:LocalProxy物件
    2. 上下文管理:
            - 請求上下文:request/session
            - App上下文: app/g
    3. 第三方元件:wtforms
        作用:
            - 生成HTML標籤
            - form表單驗證
        安裝:
            pip3 install wtforms 
            
        使用:
            - 使用者登入
            - 使用者註冊
            - 從資料庫獲取資料

內容詳細:
    1. 上下文管理:LocalProxy物件
    2. 上下文管理:
            - 請求上下文(ctx=RequestContext()):request/session
            -  App上下文(app_ctx=AppContext()): app/g
            
        - 程式啟動:
            兩個Local:
                local1 = {
                
                }
                
                local2 = {
                
                }
        
            兩個LocalStack:
                _request_ctx_stack
                _app_ctx_stack
        - 請求到來
            對資料進行封裝:
                ctx = RequestContext(request,session)
                app_ctx = AppContext(app,g)
            儲存資料:
                將包含了(app,g)資料的app_ctx物件,利用 _app_ctx_stack(貝貝,LocalStack())將app_ctx新增到Local中
                    storage = {
                        1231:{stack:[app_ctx(app,g),]}
                    }
                將包含了request,session資料的ctx物件,利用_request_ctx_stack(劉淞,LocalStack()),將ctx新增到Local中
                    storage = {
                        1231:{stack:[ctx(request,session),]}
                    }
                    
        - 檢視函式處理:
            
            
            from flask import Flask,request,session,current_app,g

            app = Flask(__name__)


            @app.route('/index')
            def index():
                # 去請求上下文中獲取值 _request_ctx_stack
                request.method # 找小東北獲取值
                session['xxx'] # 找龍泰獲取值
                
                # 去app上下文中獲取值:_app_ctx_stack 
                print(current_app)
                print(g)
                
                return "Index"


            if __name__ == '__main__':
                app.run()
                app.wsgi_app
        
        - 結束
            _app_ctx_stack.pop()
            _request_ctx_stack.pop()

            
            
        問題:
            1. Flask中g的生命週期?
            2. g和session一樣嗎?
            3. g和全域性變數一樣嗎?