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和全局变量同样吗?