Model + Form => 验证 + 数据库操作
- class LoginModelForm(xxxxx):
利用model.A中的字段
1. 生成HTML标签:class Meta: ...
2. mf = xxxModelForm(instance=ModelObj)
3. 额外的标签, is_rmb = Ffields.CharField(widget=Fwidgets.CheckboxInput())
4. 各种验证 is_valid() -> 各种钩子...
5. mf.save()
# 或
instance = mf.save(False)
instance.save()
mf.save_m2m()
a. class Meta:
1 model, # 对应Model的 2 fields=None, # 字段 3 exclude=None, # 排除字段 4 labels=None, # 提示信息 5 help_texts=None, # 帮助提示信息 6 widgets=None, # 自定义插件 7 error_messages=None, # 自定义错误信息(整体错误信息from django.core.exceptions import NON_FIELD_ERRORS) 8 field_classes=None # 自定义字段类 (也可以自定义字段) 9 localized_fields=('birth_date',) # 本地化,如:根据不同时区显示数据 10 如: 11 数据库中 12 2016-12-27 04:10:57 13 setting中的配置 14 TIME_ZONE = 'Asia/Shanghai' 15 USE_TZ = True 16 则显示: 17 2016-12-27 12:10:57
b. 验证执行过程
is_valid -> full_clean -> 钩子 -> 整体错误
c. 字典字段验证
def clean_字段名(self):
# 可以抛出异常
# from django.core.exceptions import ValidationError
return "新值"
d. 用于验证
model_form_obj = XXOOModelForm()
model_form_obj.is_valid()
model_form_obj.errors.as_json()
model_form_obj.clean()
model_form_obj.cleaned_data
e. 用于创建
model_form_obj = XXOOModelForm(request.POST)
#### 页面显示,并提交 #####
# 默认保存多对多
obj = form.save(commit=True)
# 不做任何操作,内部定义 save_m2m(用于保存多对多)
obj = form.save(commit=False)
obj.save() # 保存单表信息
obj.save_m2m() # 保存关联多对多信息
f. 用于更新和初始化
obj = model.tb.objects.get(id=1)
model_form_obj = XXOOModelForm(request.POST,instance=obj)
...
PS: 单纯初始化
model_form_obj = XXOOModelForm(initial={...})
示例:
index.html
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title></title> 6 </head> 7 <body> 8 <form action="/index/" method="POST"> 9 {% csrf_token %} 10 {{ obj.as_p }} 11 <input type="submit" value="提交" /> 12 </form> 13 </body> 14 </html>
models.py
1 from django.db import models 2 3 # Create your models here. 4 5 6 class UserType(models.Model): 7 caption = models.CharField(max_length=32) 8 9 10 class UserGroup(models.Model): 11 name = models.CharField(max_length=32) 12 13 14 class UserInfo(models.Model): 15 username = models.CharField(max_length=32) 16 email = models.EmailField() 17 user_type = models.ForeignKey(to='UserType',to_field='id') 18 u2g = models.ManyToManyField(UserGroup)
views.py
1 from django.shortcuts import render,HttpResponse 2 from app01 import models 3 4 from django import forms 5 from django.forms import fields as Ffields 6 from django.forms import widgets as Fwidgets#插件 as 设置别名 7 8 class UserInfoModelForm(forms.ModelForm): 9 #自定义字段可以在前端展示 ,不与数据库关联 10 is_rmb = Ffields.CharField(widget=Fwidgets.CheckboxInput()) 11 class Meta: 12 model = models.UserInfo#指定到一个类(表)中的字段 13 fields = '__all__'#所有字段 (列) 14 # fields = ['username','email']#可以指定的列 15 # exclude = ['username']#排除指定项 16 #定义标签 17 labels = { 18 'username': '用户名', 19 'email': '邮箱', 20 } 21 help_texts = {#帮助提示信息 22 'username': '...' 23 } 24 widgets = {#自定义插件 使用 form的插件 25 'username': Fwidgets.Textarea(attrs={'class': 'c1'}) 26 } 27 error_messages = { 28 '__all__':{ 29 #整体的错误信息 30 }, 31 'email': {#指定的错误信息 32 'required': '邮箱不能为空', 33 'invalid': '邮箱格式错误..', 34 } 35 } 36 field_classes = {#字段的类 37 # 'email': Ffields.URLField 38 } 39 40 # localized_fields=('ctime',) 41 42 def clean_username(self): 43 old = self.cleaned_data['username'] 44 return old 45 46 class UserInfoForm(forms.Form): 47 username = Ffields.CharField(max_length=32) 48 email = Ffields.EmailField() 49 user_type = Ffields.ChoiceField( 50 #从数据库取值 51 choices=models.UserType.objects.values_list('id','caption')#取选 项列表 52 ) 53 #重写父类 54 def __init__(self, *args, **kwargs): 55 super(UserInfoForm,self).__init__(*args, **kwargs) 56 self.fields['user_type'].choices = models.UserType.objects.values_list('id','caption')#更新数据 57 58 59 def index(request): 60 if request.method == "GET": 61 obj = UserInfoModelForm() 62 return render(request,'index.html',{'obj': obj}) 63 elif request.method == "POST": 64 obj = UserInfoModelForm(request.POST) 65 if obj.is_valid(): 66 # obj.save()#完成所有对应关系的保存 67 instance = obj.save(False)#手动对应关系进行保存 68 instance.save()#只保存表的数据 69 obj.save_m2m()#保存对应表的关系的表 70 71 72 # print(obj.is_valid()) 73 # print(obj.cleaned_data) 74 # print(obj.errors.as_json()) 75 return render(request,'index.html',{'obj': obj}) 76 77 #用户列表 78 def user_list(request):# 所有 跨表条件 79 li = models.UserInfo.objects.all().select_related('user_type') 80 return render(request,'user_list.html',{'li': li}) 81 #用户信息编辑 82 def user_edit(request, nid): 83 # 获取当前id对象的用户信息 84 # 显示用户已经存在数据 85 if request.method == "GET": 86 user_obj = models.UserInfo.objects.filter(id=nid).first() 87 #调用ModelForm 默认值 88 mf = UserInfoModelForm(instance=user_obj) 89 return render(request,'user_edit.html',{'mf': mf, 'nid': nid}) 90 elif request.method == 'POST': 91 user_obj = models.UserInfo.objects.filter(id=nid).first() 92 mf = UserInfoModelForm(request.POST,instance=user_obj) 93 if mf.is_valid(): 94 95 mf.save() 96 else: 97 print(mf.errors.as_json()) 98 return render(request,'user_edit.html',{'mf': mf, 'nid': nid})
user_list.html
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title></title> 6 </head> 7 <body> 8 <ul> 9 {% for row in li %} 10 <li>{{ row.username }} - {{ row.user_type.caption }} - <a href="/edit-{{ row.id }}/">编辑</a></li> 11 {% endfor %} 12 </ul> 13 </body> 14 </html>
user_edit.html
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title></title> 6 </head> 7 <body> 8 <form method="POST" action="/edit-{{ nid }}/"> 9 {% csrf_token %} 10 {{ mf.as_p }} 11 <!--显示当前对象的所有信息--> 12 <input type="submit" value="提交" /> 13 </form> 14 15 </body> 16 </html>