1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
一、form插件
django form表单类的字段和插件,字段用于表单验证获取数据,插件用来生成html代码
Field
required
=
True
, 是否允许为空
widget
=
None
, HTML插件
label
=
None
, 用于生成Label标签或显示内容
initial
=
None
, 初始值
help_text
=
'', 帮助信息(在标签旁边显示)
error_messages
=
None
, 错误信息 {
'required'
:
'不能为空'
,
'invalid'
:
'格式错误'
}
show_hidden_initial
=
False
, 是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直)
validators
=
[], 自定义验证规则
localize
=
False
, 是否支持本地化
disabled
=
False
, 是否可以编辑
label_suffix
=
None
Label内容后缀
CharField(Field)
max_length
=
None
, 最大长度
min_length
=
None
, 最小长度
strip
=
True
是否移除用户输入空白
IntegerField(Field)
max_value
=
None
, 最大值
min_value
=
None
, 最小值
DecimalField(IntegerField)
max_value
=
None
, 最大值
min_value
=
None
, 最小值
max_digits
=
None
, 总长度
decimal_places
=
None
, 小数位长度
RegexField(CharField)
regex, 自定制正则表达式
max_length
=
None
, 最大长度
min_length
=
None
, 最小长度
error_message
=
None
, 忽略,错误信息使用 error_messages
=
{
'invalid'
:
'...'
}
EmailField(CharField)
FileField(Field)
allow_empty_file
=
False
是否允许空文件
ChoiceField(Field)
...
choices
=
[], 选项,如:choices
=
[(
0
,
'上海'
),(
1
,
'北京'
),]
required
=
True
, 是否必填
widget
=
None
, 插件,默认select插件
label
=
None
, Label内容
initial
=
None
, 初始值
help_text
=
'', 帮助提示
FilePathField(ChoiceField) 文件选项,目录下文件显示在页面中
path, 文件夹路径
match
=
None
, 正则匹配
recursive
=
False
, 递归下面的文件夹
allow_files
=
True
, 允许文件
allow_folders
=
False
, 允许文件夹
required
=
True
,
widget
=
None
,
label
=
None
,
initial
=
None
,
help_text
=
''
GenericIPAddressField
protocol
=
'both'
, both,ipv4,ipv6支持的IP格式
unpack_ipv4
=
False
解析ipv4地址,如果是::ffff:
192.0
.
2.1
时候,可解析为
192.0
.
2.1
, PS:protocol必须为both才能启用
|
1
|
二、form验证规则
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
新建模块forms.py
from
django.forms
import
Form
from
django.forms
import
fields
from
django.forms
import
widgets
from
app01
import
models
import
re
from
django.core.exceptions
import
ValidationError
from
django.core.validators
import
RegexValidator
class
UserInfoForm(Form):
name
=
fields.CharField(
required
=
True
,
min_length
=
6
,
max_length
=
12
)
email
=
fields.EmailField(
required
=
True
,
)
方法一: RegexValidator对象
phone
=
fields.CharField(
validators
=
[RegexValidator(r
'^[0-9]+$'
,
'请输入数字'
), RegexValidator(r
'^159[0-9]+$'
,
'数字必须以159开头'
)]
)
方式二:函数
def
mobile_validate(value):
mobile_re
=
re.
compile
(r
'^(13[0-9]|15[0123456789]|17[678]|18[0-9]|14[57])[0-9]{8}$'
)
if
not
mobile_re.match(value):
raise
ValidationError(
'手机号码格式错误'
)
phone
=
fields.CharField(
validators
=
[mobile_validate,]
)
方法三:当前类的方法中,方法名称要求: clean_phone方法
phone
=
fields.CharField()
def
clean_phone(
self
):
# 去取用户提交的值:可能是错误的,可能是正确
value
=
self
.cleaned_data[
'phone'
]
mobile_re
=
re.
compile
(r
'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$'
)
if
not
mobile_re.match(value):
raise
ValidationError(
'手机号码格式错误'
)
if
models.UserInfo.objects.
filter
(phone
=
value).count():
raise
ValidationError(
'手机号码已经存在'
)
return
value
注册确认密码认证clean函数
class
RegisterForm(Form):
name
=
fields.CharField(
widget
=
widgets.TextInput(attrs
=
{
'class'
:
'c1'
})
)
email
=
fields.EmailField(
widget
=
widgets.EmailInput(attrs
=
{
'class'
:
'c1'
})
)
phone
=
fields.CharField(
widget
=
widgets.Textarea(attrs
=
{
'class'
:
'c1'
})
)
pwd
=
fields.CharField(
widget
=
widgets.PasswordInput(attrs
=
{
'class'
:
'c1'
})
)
pwd_confirm
=
fields.CharField(
widget
=
widgets.PasswordInput(attrs
=
{
'class'
:
'c1'
})
)
dp_id
=
fields.ChoiceField(
choices
=
[]
)
roles_id
=
fields.ChoiceField(
choices
=
[]
)
def
__init__(
self
,
*
args,
*
*
kwargs):
super
(RegisterForm,
self
).__init__(
*
args,
*
*
kwargs)
self
.fields[
'dp_id'
].choices
=
models.Depart.objects.values_list(
'id'
,
'title'
)
self
.fields[
'roles_id'
].choices
=
models.Role.objects.values_list(
'id'
,
'name'
)
def
clean(
self
):
pwd
=
self
.cleaned_data[
'pwd'
]
pwd_confirm
=
self
.cleaned_data[
'pwd_confirm'
]
if
pwd
=
=
pwd_confirm:
return
self
.cleaned_data
else
:
from
django.core.exceptions
import
ValidationError
self
.add_error(
'pwd_confirm'
, ValidationError(
'密码输入不一致'
))
return
self
.cleaned_data
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
三、中间件
项目目录下新建目录md
md目录新建middleware.py文件
from
django.shortcuts
import
HttpResponse,redirect
class
MiddlewareMixin:
def
__init__(
self
, get_response
=
None
):
self
.get_response
=
get_response
super
(MiddlewareMixin,
self
).__init__()
def
__call__(
self
, request):
response
=
None
if
hasattr
(
self
,
'process_request'
):
response
=
self
.process_request(request)
if
not
response:
response
=
self
.get_response(request)
if
hasattr
(
self
,
'process_response'
):
response
=
self
.process_response(request, response)
return
response
class
M1(MiddlewareMixin):
def
process_request(
self
, request):
print
(
'm1.process_request'
)
def
process_view(
self
, request, callback, callback_args, callback_kwargs):
print
(
'm1.process_view'
, callback)
def
process_exception(
self
,request,exception):
print
(
'm1.process_exception'
)
def
process_response(
self
,request,response):
print
(
'm1.process_response'
)
return
response
class
M2(MiddlewareMixin):
def
process_request(
self
, request):
print
(
'm2.process_request'
)
def
process_view(
self
,request,callback, callback_args, callback_kwargs):
print
(
'm2.process_view'
, callback)
def
process_response(
self
,request, response):
print
(
'm2.process_response'
)
return
response
def
process_exception(
self
,request,exception):
print
(
'm2.process_exception'
)
settings.py文件中间件添加
MIDDLEWARE
=
[
'django.middleware.security.SecurityMiddleware'
,
'django.contrib.sessions.middleware.SessionMiddleware'
,
'django.middleware.common.CommonMiddleware'
,
'django.middleware.csrf.CsrfViewMiddleware'
,
'django.contrib.auth.middleware.AuthenticationMiddleware'
,
'django.contrib.messages.middleware.MessageMiddleware'
,
'django.middleware.clickjacking.XFrameOptionsMiddleware'
,
'md.middleware.M1'
,
#添加项
'md.middleware.M2'
,
#添加项
]
中间件是一个类
中间件中一共有四个方法:
process_request
process_view
process_exception
process_response
已经添加中间件M1和M2
中间件执行时机: 请求到来,请求返回时
-
应用:
-
请求日志
-
用户登录认证
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
|
四、缓存
由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会
更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcache中,
5
分钟内再有人来访问时,则不再去执行view中的操作,而是直接从内存或者Redis中之前缓存的内容拿
到,并返回
Django中提供了
6
种缓存方式:
1.
开发调试
2.
内存
3.
文件
4.
数据库
5.
Memcache缓存(python
-
memcached模块)
6.
Memcache缓存(pylibmc模块)
a.开发调试
# 此为开始调试用,实际内部不做任何操作
# 配置:
CACHES
=
{
'default'
: {
'BACKEND'
:
'django.core.cache.backends.dummy.DummyCache'
,
# 引擎
'TIMEOUT'
:
300
,
# 缓存超时时间(默认300,None表示永不过期,0表示立即过期)
'OPTIONS'
:{
'MAX_ENTRIES'
:
300
,
# 最大缓存个数(默认300)
'CULL_FREQUENCY'
:
3
,
# 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
},
'KEY_PREFIX'
: '',
# 缓存key的前缀(默认空)
'VERSION'
:
1
,
# 缓存key的版本(默认1)
'KEY_FUNCTION'
函数名
# 生成key的函数(默认函数会生成为:【前缀:版本:key】)
}
}
def
default_key_func(key, key_prefix, version):
return
'%s:%s:%s'
%
(key_prefix, version, key)
def
get_key_func(key_func):
if
key_func
is
not
None
:
if
callable
(key_func):
return
key_func
else
:
return
import_string(key_func)
return
default_key_func
b. 内存缓存
此缓存将内容保存至内存的变量中
# 配置:
CACHES
=
{
'default'
: {
'BACKEND'
:
'django.core.cache.backends.locmem.LocMemCache'
,
'LOCATION'
:
'unique-snowflake'
,
}
}
c. 文件缓存
# 此缓存将内容保存至文件
# 配置:
CACHES
=
{
'default'
: {
'BACKEND'
:
'django.core.cache.backends.filebased.FileBasedCache'
,
'LOCATION'
:
'/var/tmp/django_cache'
,
}
}
d. 数据库缓存
# 此缓存将内容保存至数据库
# 配置:
CACHES
=
{
'default'
: {
'BACKEND'
:
'django.core.cache.backends.db.DatabaseCache'
,
'LOCATION'
:
'my_cache_table'
,
# 数据库表
}
}
e. Memcache缓存(python
-
memcached模块)
# 此缓存使用python-memcached模块连接memcache
CACHES
=
{
'default'
: {
'BACKEND'
:
'django.core.cache.backends.memcached.MemcachedCache'
,
'LOCATION'
:
'127.0.0.1:11211'
,
}
}
CACHES
=
{
'default'
: {
'BACKEND'
:
'django.core.cache.backends.memcached.MemcachedCache'
,
'LOCATION'
:
'unix:/tmp/memcached.sock'
,
}
}
CACHES
=
{
'default'
: {
'BACKEND'
:
'django.core.cache.backends.memcached.MemcachedCache'
,
'LOCATION'
: [
'172.19.26.240:11211'
,
'172.19.26.242:11211'
,
]
}
}
f. Memcache缓存(pylibmc模块)
# 此缓存使用pylibmc模块连接memcache
CACHES
=
{
'default'
: {
'BACKEND'
:
'django.core.cache.backends.memcached.PyLibMCCache'
,
'LOCATION'
:
'127.0.0.1:11211'
,
}
}
CACHES
=
{
'default'
: {
'BACKEND'
:
'django.core.cache.backends.memcached.PyLibMCCache'
,
'LOCATION'
:
'/tmp/memcached.sock'
,
}
}
CACHES
=
{
'default'
: {
'BACKEND'
:
'django.core.cache.backends.memcached.PyLibMCCache'
,
'LOCATION'
: [
'172.19.26.240:11211'
,
'172.19.26.242:11211'
,
]
}
}
缓存使用方法
1.
全站应用配置
使用中间件,经过一系列的认证等操作,如果内容在缓存中存在,则使用FetchFromCacheMiddleware获
取内容并返回给用户,当返回给用户之前,判断缓存中是否已经存在,如果不存在则
UpdateCacheMiddleware会将缓存保存至缓存,从而实现全站缓存
MIDDLEWARE
=
[
'django.middleware.cache.UpdateCacheMiddleware'
,
# 其他中间件...
'django.middleware.cache.FetchFromCacheMiddleware'
,
]
#CACHE_MIDDLEWARE_ALIAS = ""
# CACHE_MIDDLEWARE_SECONDS = ""
# CACHE_MIDDLEWARE_KEY_PREFIX = ""
2.
单独视图函数
方式一:
from
django.views.decorators.cache
import
cache_page
@cache_page
(
60
*
15
)
def
my_view(request):
...
方式二:
from
django.views.decorators.cache
import
cache_page
urlpatterns
=
[
url(r
'^foo/([0-9]{1,2})/$'
, cache_page(
60
*
15
)(my_view)),
]
3.
局部视图使用
a. 引入TemplateTag
{
%
load cache
%
}
b. 使用缓存
{
%
cache
5000
缓存key
%
}
缓存内容
{
%
endcache
%
}
五、信号
1.
内置信号
Django中提供了“信号调度”,用于在框架执行操作时解耦。通俗来讲,就是一些动作发生的时候,
信号允许特定的发送者去提醒一些接受者
Model signals
pre_init
# django的modal执行其构造方法前,自动触发
post_init
# django的modal执行其构造方法后,自动触发
pre_save
# django的modal对象保存前,自动触发
post_save
# django的modal对象保存后,自动触发
pre_delete
# django的modal对象删除前,自动触发
post_delete
# django的modal对象删除后,自动触发
m2m_changed
# django的modal中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发
class_prepared
# 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发
Management signals
pre_migrate
# 执行migrate命令前,自动触发
post_migrate
# 执行migrate命令后,自动触发
Request
/
response signals
request_started
# 请求到来前,自动触发
request_finished
# 请求结束后,自动触发
got_request_exception
# 请求异常后,自动触发
Test signals
setting_changed
# 使用test测试修改配置文件时,自动触发
template_rendered
# 使用test测试渲染模板时,自动触发
Database Wrappers
connection_created
# 创建数据库连接时,自动触发
对于Django内置的信号,仅需注册指定信号,当程序执行相应操作时,自动触发注册函数:
from
django.core.signals
import
request_finished
from
django.core.signals
import
request_started
from
django.core.signals
import
got_request_exception
from
django.db.models.signals
import
class_prepared
from
django.db.models.signals
import
pre_init, post_init
from
django.db.models.signals
import
pre_save, post_save
from
django.db.models.signals
import
pre_delete, post_delete
from
django.db.models.signals
import
m2m_changed
from
django.db.models.signals
import
pre_migrate, post_migrate
from
django.test.signals
import
setting_changed
from
django.test.signals
import
template_rendered
from
django.db.backends.signals
import
connection_created
def
callback(sender,
*
*
kwargs):
print
(
"xxoo_callback"
)
print
(sender,kwargs)
xxoo.connect(callback)
# xxoo指上述导入的内容
例子:
from
django.core.signals
import
request_finished
from
django.dispatch
import
receiver
@receiver
(request_finished)
def
my_callback(sender,
*
*
kwargs):
print
(
"Request finished!"
)
2.
自定义信号
a. 定义信号
import
django.dispatch
pizza_done
=
django.dispatch.Signal(providing_args
=
[
"toppings"
,
"size"
])
b. 注册信号
def
callback(sender,
*
*
kwargs):
print
(
"callback"
)
print
(sender,kwargs)
pizza_done.connect(callback)
c. 触发信号
from
路径
import
pizza_done
pizza_done.send(sender
=
'seven'
,toppings
=
123
, size
=
456
)
例子请求后打印一行数据: 配置在urls.py一层目录下面的__init__.py文件中
from
django.core.signals
import
request_finished
from
django.core.signals
import
request_started
from
django.core.signals
import
got_request_exception
from
django.db.models.signals
import
class_prepared
from
django.db.models.signals
import
pre_init, post_init
from
django.db.models.signals
import
pre_save, post_save
from
django.db.models.signals
import
pre_delete, post_delete
from
django.db.models.signals
import
m2m_changed
from
django.db.models.signals
import
pre_migrate, post_migrate
from
django.test.signals
import
setting_changed
from
django.test.signals
import
template_rendered
from
django.db.backends.signals
import
connection_created
def
test(sender,
*
*
kwargs):
print
(
"request_finished.222"
)
print
(sender, kwargs)
request_started.connect(test)
#请求开始时打印
request_finished.connect(test)
#请求结束后打印
|
本文转自小白的希望 51CTO博客,原文链接:http://blog.51cto.com/haoyonghui/1966329
,如需转载请自行联系原作者