27)django-form操作示例(动态Select数据,自定义字段验证,全局验证等)
2017-11-19 17:31
633 查看
1)普通传递select数据
# -*- coding:utf-8 -*- __author__ = 'shisanjun' from django import forms from django.forms import fields,widgets class UserInfoForm(forms.Form): user=fields.CharField( required=False, widget=widgets.Textarea(attrs={"class":"c1"}), ) pwd=fields.CharField( max_length=12, widget=widgets.PasswordInput(attrs={"class":"c1"}) ) user_type=fields.ChoiceField( choices=[(1,"普通用户"),(2,"超级用户")], widget=widgets.Select, ) <form action='{% url "index" %}' method="post"> <p> {{ obj.user }} </p> <p>{{ obj.pwd }}</p> <p>{{ obj.user_type }}</p> </form>
2)上面choice应该从数据库中取数据
from django import forms from django.forms import fields,widgets from app01 import models class UserInfoForm(forms.Form): user=fields.CharField( required=False, widget=widgets.Textarea(attrs={"class":"c1"}), ) pwd=fields.CharField( max_length=12, widget=widgets.PasswordInput(attrs={"class":"c1"}) ) user_type=fields.ChoiceField( #choices=[(1,"普通用户"),(2,"超级用户")], choices=models.UserType.objects.all().values_list("id","name"),#要返回元组列表 widget=widgets.Select, )
3)上面有个问题,就是数据库中新增加的数据,需要重起服务才能加载新数据。
这是什么原因造成的? 上面user,pwd,user_type都是放在类里面的,都是静态字段,数据加载都是一次性加载在内存里面的。 #解决: def index(request): from app01 import forms obj=forms.UserInfoForm() obj.fields#这里面封装了user,pwd,user_type,当数据库有新的数据的时候从新赋值 obj.fields["user_type"].choices=models.UserType.objects.all().values_list("id","name") return render(request,"index.html",{"obj":obj})
4)上面如果有很多choince,那要写很多,怎么改进(两种方法)
重新构造form的__init__()方法。在init里面赋值上面也是对类对象的实例重新赋值。 #方法1 # -*- coding:utf-8 -*- __author__ = 'shisanjun' from django import forms from django.forms import fields,widgets from app01 import models class UserInfoForm(forms.Form): user=fields.CharField( required=False, widget=widgets.Textarea(attrs={"class":"c1"}), ) pwd=fields.CharField( max_length=12, widget=widgets.PasswordInput(attrs={"class":"c1"}) ) user_type=fields.ChoiceField( #choices=[(1,"普通用户"),(2,"超级用户")], choices=models.UserType.objects.all().values_list("id","name"), widget=widgets.Select, ) def __init__(self,*args,**kwargs): super(UserInfoForm,self).__init__(*args,**kwargs) self.fields["user_type"].choices=models.UserType.objects.all().values_list("id","name") #方法2 -*- coding:utf-8 -*- __author__ = 'shisanjun' from django import forms from django.forms import fields,widgets from app01 import models class UserInfoForm(forms.Form): user=fields.CharField( required=False, widget=widgets.Textarea(attrs={"class":"c1"}), ) pwd=fields.CharField( max_length=12, widget=widgets.PasswordInput(attrs={"class":"c1"}) )
#方法1 user_type=fields.ChoiceField( #choices=[(1,"普通用户"),(2,"超级用户")], choices=[],#这里不用赋值,原因实例化的时候init会赋值 widget=widgets.Select, ) #方法2 user_type2=fields.CharField(widget=widgets.Select(choices=[])) def __init__(self,*args,**kwargs): super(UserInfoForm,self).__init__(*args,**kwargs) self.fields["user_type"].choices=models.UserType.objects.all().values_list("id","name") #方法2 self.fields["user_type2"].widget.choices=models.UserType.objects.all().values_list("i
d","name")[/code]
5)上面从数据库取数据也django也可以自己做,但是不太好。
from django.forms.models import ModelChoiceField user_type3=ModelChoiceField( queryset=models.UserType.objects.all(),#django会自动取 ) 这里是有代价的,要在model里面加__str__,不然显示的名称是对象 class UserType(models.Model): name=models.CharField(max_length=32) def __str__(self): return self.name # -*- coding:utf-8 -*- __author__ = 'shisanjun' from django import forms from django.forms import fields,widgets from app01 import models from django.forms.models import ModelChoiceField class UserInfoForm(forms.Form): user=fields.CharField( required=False, widget=widgets.Textarea(attrs={"class":"c1"}), ) pwd=fields.CharField( max_length=12, widget=widgets.PasswordInput(attrs={"class":"c1"}) ) user_type=fields.ChoiceField( #choices=[(1,"普通用户"),(2,"超级用户")], choices=[],#这里不用赋值,原因实例化的时候init会赋值 widget=widgets.Select, ) #方法2 user_type2=fields.CharField(widget=widgets.Select(choices=[])) #方法3 user_type3=ModelChoiceField( empty_label="请选择", queryset=models.UserType.objects.all(),#django会自动取 ) def __init__(self,*args,**kwargs): super(UserInfoForm,self).__init__(*args,**kwargs) self.fields["user_type"].choices=models.UserType.objects.all().values_list("id","name") #方法2 self.fields["user_type2"].widget.choices=models.UserType.objects.all().
values_list("id","name")
6)默认值
def index(request): from app01 import forms obj=forms.UserInfoForm()#如果这里赋值字典就是显示默认值(初始化) obj.fields#这里面封装了user,pwd,user_type,当数据库有新的数据的时候从新赋值 #obj.fields["user_type"].choices=models.UserType.objects.all().values_list("id","name") return render(request,"index.html",{"obj":obj})
7)用户验证
def index(request): if request.method=="GET": obj=forms.UserInfoForm()#如果这里赋值字典就是显示默认值(初始化) obj.fields#这里面封装了user,pwd,user_type,当数据库有新的数据的时候从新赋值 #obj.fields["user_type"].choices=models.UserType.objects.all().values_list("id","name") return render(request,"index.html",{"obj":obj}) elif request.method=="POST": obj=forms.UserInfoForm(request.POST,request.FILES) obj.is_valid()#他是基于什么验证的,根据from模板验证。form会为长度,为空等验证,但是如果用户已存在,就不应该进行上面验证。 # -*- coding:utf-8 -*- __author__ = 'shisanjun' from django import forms from django.forms import fields,widgets from app01 import models from django.forms.models import ModelChoiceField from django.core.exceptions import ValidationError class UserInfoForm(forms.Form): user=fields.CharField( required=False, widget=widgets.Textarea(attrs={"class":"c1"}), ) pwd=fields.CharField( max_length=12, widget=widgets.PasswordInput(attrs={"class":"c1"}) ) user_type=fields.ChoiceField( #choices=[(1,"普通用户"),(2,"超级用户")], choices=[],#这里不用赋值,原因实例化的时候init会赋值 widget=widgets.Select, ) #方法2 user_type2=fields.CharField(widget=widgets.Select(choices=[])) #方法3 user_type3=ModelChoiceField( empty_label="请选择", queryset=models.UserType.objects.all(),#django会自动取 ) def __init__(self,*args,**kwargs): super(UserInfoForm,self).__init__(*args,**kwargs) self.fields["user_type"].choices=models.UserType.objects.all().values_list("id","name") #方法2 self.fields["user_type2"].widget.choices=models.UserType.objects.all().values_list("id","name") class RegiesterForm(forms.Form): user=fields.CharField()#一个字段一个字段的循环,这里通过了,才会到clean_user,下面以次类推 email=fields.EmailField() def clean_user(self): #通过调用form预留的钩子,clean_user单独对user做验证 c=models.Userinfo.objects.filter(name=self.cleaned_data['user']) #如果数据库中有,应该给页面报错了,显示用户已存在 if not c: return self.cleaned_data['user'] #返回原来值 else: #如果没有抛出valideionError raise ValidationError("用户名已存在",code="xxx") def clean_email(self): pass
8)如果用户名不对,错误显示在用户名旁边。(上面是单独给字段写的钩子),也可以对整个form做钩子验证。
class LoginForm(forms.Form): user=fields.CharField()#一个字段一个字段的循环,这里通过了,才会到clean_user,下面以次类推 pwd=fields.CharField() email=fields.EmailField() def clean_user(self): #通过调用form预留的钩子,clean_user单独对user做验证 c=models.Userinfo.objects.filter(name=self.cleaned_data['user']) #如果数据库中有,应该给页面报错了,显示用户已存在 if not c: return self.cleaned_data['user'] #返回原来值 else: #如果没有抛出valideionError raise ValidationError("用户名已存在",code="user") def clean_email(self): pass def clean(self): #对整体验证 #判断用户名和密码是否存在 c= models.Userinfo.objects.filter(user=self.cleaned_data["user"],password=self.cleaned_data["pwd"]) if not c: return self.cleaned_data #源码中self.cleaned_data=cleaned_data else: raise ValidationError("用户名或密码错误")
源码中一共有3个钩子
self._clean_fields()对字段验证 self._clean_form()对整体验证 self._post_clean()
form验证经历阶段:数据来了-->到相应的form-->先拿到第一个字段,先进行正则表达式判断完,然后执行字段的钩子,--〉所有字段运行完了到clean(),最后到postclean()
is_valid()--->self.errors-->full_clean --> self._clean_fields()对字段验证 self._clean_form()对整体验证 self._post_clean()
views中错误信息
#views.py def register(request): obj=forms.RegiesterForm(request.POST) if obj.is_valid(): #下面操作,可以在is_valid做验证 #obj.cleaned_data[''] obj.cleaned_data() else: obj.errors #obj.errors就是个字段,每个字段的错误放在各自的字段里面,整体clean错误放在那里了 from django.core.exceptions import NON_FIELD_ERRORS """ '__all__':[],整体的错误信息clean抛出的异常都在这里==〉NON_FIELD_ERRORS NON_FIELD_ERRORS:[], 'user':['code':required,'message':'xxx'], 'pwd':['code':required,'message':'xxx'], """ account.py from django.shortcuts import redirect,render,HttpResponse from django import forms from django.forms import fields from django.forms import widgets from app01 import models from django.core.exceptions import ValidationError import json class LoginForm(forms.Form): user=fields.CharField()#一个字段一个字段的循环,这里通过了,才会到clean_user,下面以次类推 pwd=fields.CharField() email=fields.EmailField() def clean_user(self): #通过调用form预留的钩子,clean_user单独对user做验证 c=models.Userinfo.objects.filter(name=self.cleaned_data['user']) #如果数据库中有,应该给页面报错了,显示用户已存在 if not c: return self.cleaned_data['user'] #返回原来值 else: #如果没有抛出valideionError raise ValidationError("用户名已存在",code="user") def clean_email(self): pass # # def clean(self): #对整体验证 # # #判断用户名和密码是否存在 # c= models.Userinfo.objects.filter(user=self.cleaned_data["user"],password=self.cleaned_data["pwd"]) # if not c: # return self.cleaned_data #源码中self.cleaned_data=cleaned_data # else: # ValidationError("用户名或密码错误") class JsonCustomEncoder(json.JSONEncoder): from django.core.exceptions import ValidationError def default(self, field): if isinstance(field,ValidationError): return {'code':field.code,'message':field.messages} else: return json.JSONEncoder.default(self,field) def login(request): res={"status":False,"data":None,"error":None} if request.method=="GET": return render(request,"login.html") elif request.method=="POST": obj=LoginForm(request.POST) if obj.is_valid(): print(obj.cleaned_data) res["status"]=True else: #res["error"]=obj.errors.as_json() #为什么不用as_json,as_json返回的是字典,所以res就会变成嵌套字典,json不能转嵌套字典,下面用as_data()结合cls定制 #print(obj.errors.as_data())#errors.as_data()返回的是 ValidationError类型,不是字典,不能直接序列化 res["error"]=obj.errors.as_data() result=json.dumps(res,cls=JsonCustomEncoder)#dumps有个参数cls,可以定制 return HttpResponse(json.dumps(result)) #obj.errors返回的是ErrorDict,不是字典(虽然继承字典) #obj.errors.as_json() 返回的字符串(前端要连续反解两次) #obj.errors.as_data() 返回原生的字典 但是返回value 是ValidationError,不能直接序列化 模板 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form id="fm"> {% csrf_token %} <p> <input type="text" name="username"> </p> <p> <input type="text" name="password"> </p> <a id="submit">提交</a> </form> <script src="/static/jquery-1.12.4.js"></script> <script> $(function(){ //框架自加载 $("#submit").click( function(){ $.ajax( { url:"{% url 'login' %}", type:"post", data:$("#fm").serialize(), success:function(arg){ arg=JSON.parse(arg); console.log(arg); }, error:function(arg){ console.log(arg); } } ) } ) }) </script> </body>
相关文章推荐
- django(7)modelform操作及验证、ajax操作普通表单数据提交、文件上传、富文本框基本使用
- 关于form表单中动态添加数据的验证
- 5.django笔记之form保存表单信息,动态select
- django框架自定义用户表操作示例
- 智能表单设计器Web Free Form Designer:FreeForm动态数据验证和动态自动计算
- Django Form之动态数据初始化
- 使用Django的ModelForm对表单进行自动验证(可自定义验证规则)
- Django—Form两种解决表单数据无法动态刷新的方法
- 【Django】Django—Form两种解决表单数据无法动态刷新的方法
- Python cookbook(数据结构与算法)根据字段将记录分组操作示例
- Django-Form表单(验证、定制、错误信息、Select)
- Django数据模型动态增删字段(更改数据库模式)
- Django Form 自定义字段错误信息
- python3开发进阶-Django框架中form的查看校验方法is_valid()的源码,自定义验证方法
- Django中button的处理 & ajax提交数据时不走Form组件验证
- Sql2012如何将远程服务器数据库及表、表结构、表数据导入本地数据库 自定义日志记录功能,按日记录,很方便 C#常量和字段以及各种方法的语法总结 类型,对象,线程栈,托管堆在运行时的关系,以及clr如何调用静态方法,实例方法,和虚方法 asp.net webapi 自定义身份验证
- 使用Django Form解决表单数据无法动态刷新的两种方法
- .Net高级进阶,教你如何构建企业模型数据拦截层,动态控制字段验证
- 智能表单设计器Web Free Form Designer:FreeForm动态数据验证和动态自动计算
- .Net高级进阶,教你如何构建企业模型数据拦截层,动态控制字段验证