您的位置:首页 > 编程语言 > Python开发

python3-开发进阶Flask的基础(4)

2018-08-24 19:08 851 查看
今日内容:

上下文管理:LocalProxy对象

上下文管理: 请求上下文: request/session app上下文:app/g

第三方组件:wtforms 1、使用 2、原理   

一、LocalProxy

首先我们一看一段自己写的代码:

#test.py
DATA={
'request':{
'method':'GET',
'form':{}
},
'session':{
'user':'duoduo',
'age':'20'
}
}

class LocalProxy(object):   #

def __init__(self,key):
self.key=key

def get_dict(self):
return DATA[self.key]

def __str__(self):
return 'duoduo'

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')


LocalProxy的类就相当于一个代理


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.baidu.com')

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':'duoduo','city':3})
form = UserForm()
return render_template('user.html',form=form)

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


test.py
先思考几个问题:

1、form 对象为什么可以for循环?

变成一个可迭代对象,类中含有__iter__,并且返回一个迭代器

class Foo(object):
# def __iter__(self):
#     return iter([11,22,33])   #值是11,22,33

def __iter__(self):
yield 1
yield 2
yield 3
obj=Foo()

for item in obj:
print(item)


2、__new__方法返回值决定对象到底是什么

class Bar(object):
def __init__(self,cls):
self.cls=cls

class Foo(object):
def __new__(cls, *args, **kwargs):
#return super(Foo,cls).__new__(cls,*args,**kwargs)  <__main__.Foo object at 0x0000023741EEAC88>
return  Bar(cls)    #<__main__.Bar object at 0x0000013FC1ABA4E0>

obj=Foo()
print(obj)


3、metaclass

创建类时,先执行type的__init__方法,当一个类实例化时,

执行type的__call__方法, 先执行类的__new__,创建对象再执行类的__init__,初始化

__call__方法的返回值就是实例化的对象

#类创建的两种方式      类是type创建的

#1、
# class Foo(object):
#     a1=123
#     def func(self):
#         return 666

# Foo=type('Foo',(object,),{'a1':123,'func':lambda self:666})

#2、自定义type
#
# class MyType(type):
#     pass
#
# class Foo(object,metaclass=MyType):  #指定当前类由谁创建
#     a1=123
#     def func(self):
#         return 666

# Foo=MyType('Foo',(object,),{'a1':123,'func':lambda self:666})

#3、metaclass 作用
#指定当前类由谁来创建

class MyType(type):
def __init__(self,*args,**kwargs):
super(MyType,self).__init__(*args,**kwargs)

def __call__(cls, *args, **kwargs):
obj=cls.__new__(cls)
cls.__init__(obj,*args, **kwargs)
return obj

class Foo(object,metaclass=MyType):
a1=123

def __init__(self):
pass

def __new__(cls, *args, **kwargs):
return object.__new__(cls)

def func(self):
return 666

#Foo是类
#Foo是MyType的一个对象

obj=Foo()


4、wtforms的实现

from wtforms import Form  #先点开Form








我们创建的类没有metaclass但他继承的父类,有指定metaclass,就按照父类的来创建类



看看FormMeta 中的__init__方法做了什么事?



实例化时先执行__new__







UnboundField类是做什么的?





做完自己的操作,再执行父类的__call__,然后type会调用自己__new__方法,__init__方法



下面Form 的序列化





源码:

类的创建 type.__init__

对象的创建 type.__call__ 1、类.__new__ 2、类.__init__
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: