1.7 flask 的元件 wtfroms使用
阿新 • • 發佈:2019-01-07
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和全域性變數一樣嗎?