1. 搭建环境请参考:http://www.cnblogs.com/momo8238/p/7508677.html
二、Form操作
一般会创建forms.py文件,单独存放form模块。
Form 专门做数据验证,而且非常强大。有以下两个插件:
1-fields :验证(肯定会用的)
2-widgets:生成HTML(有时候用,有时候可以不用)
2.1一般新url方式操作用widgets,因为生成url不是关键的,可以保留上一次提交的数据
2.2Ajax请求的时候,可以不用它生成html
1.1、Form操作动态Select数据
urls.py
1
|
|
views.py
1
2
3
4
|
|
forms.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
|
models.py
1
2
|
|
index.html
1
2
3
4
5
6
|
|
上面有个问题,就是数据库添加数据后,django需要重启网页才能看到新加的数据。why?
forms里面,定义的类,类里的user、pwd、user_type都是静态字段(类变量),这些都是属于类的。
在
__init__
里面写的属于对象。
而启动Django的时候,类变量一次性都加在到内存了。
上面views.py里的
obj = UserInfoForm()
生成了一个对象,会执行类里的
__init__
方法,会把类里的字段封装到obj.fields里面(里面有user、pwd、user_type三个字段),所以:
views.py
1
2
3
4
5
6
7
8
9
|
|
这样,数据库添加数据,网页上就可以实时更新了。但是如果有很多choices的话,也会写很多,也不好。
所以不在views.py里做修改,可以在forms.py里类的
__init__
构造方法里写
forms.py
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
|
|
1.2、Form操作动态Select数据
上面1.1里是自己获取实现的,Django也可以自动实现,只是实现的不太好。
django 里自动实现的,看user_type3
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
|
|
使用Django自动提供的这个方法,有一点不好的就是:需要自己在models里加上
__str__
方法
1
2
3
4
5
|
|
ModelChoiceField 参数
1
2
3
4
5
6
|
|
ModelChoiceField 是单选的,多选的是:ModelMultipleChoiceField
2、Form内置钩子(数据验证)
初始化操作
加一个字典,生成显示默认值
views.py
1
2
3
4
|
|
数据验证
views.py
1
2
3
4
5
6
7
8
9
10
|
|
正则表达式验证成功了,但是如果用户名重复了,也是不让执行的,如何自定制呢?
注册数据验证示例
forms.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
|
登录数据验证示例
forms.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
|
验证顺序
这么多钩子,这么强大的数据验证,验证顺序是:
form循环,
- 先第一个字段正则表达式判断,执行字段钩子函数;
- 第二个字段正则,第二个的钩子;
- 所有字段完成后,执行clean钩子;
-
clean执行完后,执行
_post_clean
钩子
怎么去记:
通过看源码去找:
先找
is_valid
,找到
errors
,找到
full_clean
,所有的钩子基于
full_clean
执行的
验证完成后
views.py(伪代码)
1 def register(request): 2 from cmdb.forms import RegisterForm 3 from django.core.exceptions import NON_FIELD_ERRORS 4 obj = RegisterForm(request.POST) 5 if obj.is_valid(): 6 obj.cleand_data 7 8 else: 9 obj.errors 10 { 11 'user':[{'code':'required','message':'xxxx'}], 12 'pwd':[{'code':'required','message':'xxxx'}], 13 # 上面每个字段的错误信息放在里面,那clean总的错误信息放在哪里? 14 '__all__':[], # 特殊的整体错误信息,放在这里 15 # NON_FIELD_ERRORS:[], 和 __all__ 一个意思。 16 }
3、Form内置序列化错误信息
不管提交数据是浏览器提交、还是curl方式,还是ajax提交,只要是
request.POST
都可以做验证。
Ajax 提交数据,进行验证
urls.py
1 url(r'^login.html$', views.login),
views.py
1 from django import forms 2 from django.forms import widgets, fields 3 class LoginForm(forms.Form): 4 username = fields.CharField() 5 password = fields.CharField( 6 max_length=64, 7 min_length=12 8 ) 9 10 def login(request): 11 import json 12 res = {'status':True, 'error':None, 'data': None} 13 if request.method == "GET": 14 return render(request,"login.html") 15 elif request.method == "POST": 16 obj = LoginForm(request.POST) 17 if obj.is_valid(): 18 print(obj.cleand_data) 19 else: 20 # print(obj.errors, type(obj.errors)) 21 res['error'] = obj.errors.as_json() # 转为json格式 22 return HttpResponse(json.dumps(res))
login.html
1 <body> 2 <form id="fm"> 3 {% csrf_token %} 4 <p><input type="text" name="username" /></p> 5 <p><input type="password" name="password" /></p> 6 <a id="submit">ajax提交</a> 7 </form> 8 <script src="/static/jquery-1.12.4.js"></script> 9 <script> 10 // 页面框架加载完自动执行 11 $('#submit').click(function(){ 12 $.ajax({ 13 url:'/login.html', 14 type:'POST', 15 data:$('#fm').serialize(), 16 success:function(arg){ 17 console.log(arg); 18 arg = JSON.parse(arg); // 转为字典 19 console.log(arg); 20 }, 21 error: function(){ 22 23 } 24 }) 25 }) 26 </script> 27 </body>
上面的方式可以实现,只是前端需要反解两次,不太好,下面优化一下。
- as_json : 生成json格式
- as_data : 生成dict数据。
views.py
1 from django import forms 2 from django.forms import widgets, fields 3 class LoginForm(forms.Form): 4 username = fields.CharField() 5 password = fields.CharField( 6 max_length=64, 7 min_length=12 8 ) 9 10 # 序列化,转换为指定数据类型 11 import json 12 from django.core.exceptions import ValidationError 13 class JsonCustomEncoder(json.JSONEncoder): 14 def default(self, field): 15 if isinstance(field, ValidationError): 16 return {'code':field.code, 'messages': field.messages} 17 else: 18 return json.JSONEncoder.default(self, field) 19 20 def login(request): 21 res = {'status':True, 'error':None, 'data': None} 22 if request.method == "GET": 23 return render(request,"login.html") 24 elif request.method == "POST": 25 obj = LoginForm(request.POST) 26 if obj.is_valid(): 27 print(obj.cleand_data) 28 else: 29 # print(obj.errors, type(obj.errors)) 30 # res['error'] = obj.errors.as_json() # 转为json格式 31 print(type(obj.errors.as_data())) 32 for k,v in obj.errors.as_data().items(): 33 print(k,v) # 这里v是ValidationError类型,不能序列化 34 res['error'] = obj.errors.as_data() 35 result = json.dumps(res, cls=JsonCustomEncoder) 36 return HttpResponse(json.dumps(result))
4、Django 序列化操作
Json.dumps
用来做序列化,但是只能序列化一些简单的基本数据类型。对于无法序列化的数据类型,只能自定制了。
ErrorDict自定义JSONEncoder
由于json.dumps时无法处理datetime日期,所以可以通过自定义处理器来做扩展,如:
1 import json 2 from datetime import date 3 from datetime import datetime 4 5 class JsonCustomEncoder(json.JSONEncoder): 6 7 def default(self, field): 8 9 if isinstance(field, datetime): 10 return o.strftime('%Y-%m-%d %H:%M:%S') 11 elif isinstance(field, date): 12 return o.strftime('%Y-%m-%d') # 转成字符串类型 13 else: 14 return json.JSONEncoder.default(self, field) 15 16 v = {'k':'123', "k1":datetime.datetime.now()} 17 ds = json.dumps(v, cls=JsonCustomEncoder)
QuerySet 第一种序列化方式
上面自己写实现也可以,不过Django提供了方法做序列化
1 from django.core import serializers 2 3 v = models.tb.objects.all() 4 data = serializers.serialize("json", v)
QuerySet 第二种序列化方式
1 import json 2 from datetime import date 3 from datetime import datetime 4 5 class JsonCustomEncoder(json.JSONEncoder): 6 7 def default(self, field): 8 9 if isinstance(field, datetime): 10 return field.strftime('%Y-%m-%d %H:%M:%S') 11 elif isinstance(field, date): 12 return field.strftime('%Y-%m-%d') 13 else: 14 return json.JSONEncoder.default(self, field) 15 16 v = models.tb.objects.values('id','name','ctime') 17 v = list(v) # 把(类似列表的queryset类型)转换为列表 18 v = json.dumps(v,cls=JsonCustomEncoder) # 这里cls只对ctime操作。 19 # 如果没有ctime这个类型,只写上边的三句就可以实现
注:form里
__all__
整体的错误信息,前端展示如下:
{
{ obj.non_field_errors }}
转载于:https://www.cnblogs.com/gaodi2345/p/11587341.html