2019-1-7 17:59:37html
還有兩天左右flask就結束啦!昨晚逛了一下吾愛破解還有慕課,發現有三個意外項目,前端
Django生鮮項目,flask電影網站項目,vue美團網項目,都保存百度雲啦,寒假能夠搞事情啦vue
還有十天左右的視頻,看完後認證整理博客,而後爭取整理本書,到時候回學校打印,233333333!html5
想一想都是頗有成就感的一件事情!mysql
越努力,越幸運!永遠不要高估本身!sql
今天講了wtfroms 組件,就是Django中的form modelsForm 相似!數據庫
書上介紹的組件不少,flask那本書!django
flask參考連接: https://www.cnblogs.com/wupeiqi/articles/8202357.htmlflask
還講了 重要的東西 localproxysession
這是關於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)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{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和全局變量同樣嗎?