Django之ModelForm

ModelForm:

 应用场景:
            - ModelForm - 中小型应用程序。因为ModelForm是依赖于models的
            - Form      - 大型应用程序  *

 1 ModelForm
 2     a.  class Meta:
 3             model,                           # 对应Model的
 4             fields=None,                     # 字段
 5             exclude=None,                    # 排除字段
 6             labels=None,                     # 提示信息
 7             help_texts=None,                 # 帮助提示信息
 8             widgets=None,                    # 自定义插件
 9             error_messages=None,             # 自定义错误信息(整体错误信息from django.core.exceptions import NON_FIELD_ERRORS)
10             field_classes=None               # 自定义字段类 (也可以自定义字段)
11             localized_fields=('birth_date',) # 本地化,如:根据不同时区显示数据
12             如:
13                 数据库中
14                     2016-12-27 04:10:57
15                 setting中的配置
16                     TIME_ZONE = 'Asia/Shanghai'
17                     USE_TZ = True
18                 则显示:
19                     2016-12-27 12:10:57
20     b. 验证执行过程
21         is_valid -> full_clean -> 钩子 -> 整体错误
22  
23     c. 字典字段验证
24         def clean_字段名(self):
25             # 可以抛出异常
26             # from django.core.exceptions import ValidationError
27             return "新值"
28     d. 用于验证
29         model_form_obj = XXOOModelForm()
30         model_form_obj.is_valid()
31         model_form_obj.errors.as_json()
32         model_form_obj.clean()
33         model_form_obj.cleaned_data
34     e. 用于创建
35         model_form_obj = XXOOModelForm(request.POST)
36         #### 页面显示,并提交 #####
37         # 默认保存多对多
38             obj = form.save(commit=True)
39         # 不做任何操作,内部定义 save_m2m(用于保存多对多)
40             obj = form.save(commit=False)
41             obj.save()      # 保存单表信息
42             obj.save_m2m()  # 保存关联多对多信息
43  
44     f. 用于更新和初始化
45         obj = model.tb.objects.get(id=1)
46         model_form_obj = XXOOModelForm(request.POST,instance=obj)
47         ...
48  
49         PS: 单纯初始化
50             model_form_obj = XXOOModelForm(initial={...})
 1             - 1. 类 
 2                   class Foo(ModelForm):
 3                     class Meta:
 4                         # model = models.Role
 5                         # fields = "__all__"
 6                         # fields = ['caption',]
 7                         # exclude = ['catpion']
 8                         model = models.UserType
 9                         fields = "__all__"
10 
11                         error_messages = {
12                             'title':{'required':'名称不能为空','invalid':'格式错误'}
13                         }
14                         widgets = {
15                             'title':wd.TextInput(attrs={'class':'c1'})
16                         }
17                 
18             - 2. 添加
19                  GET:
20                     form = Foo()
21                  POST:
22                     form = Foo(data=request.POST)
23                     form.is_valid()
24                     form.cleaned_data
25                     form.erros
26                     form.save()
27             - 3. 修改
28                  GET:
29                     form = Foo(instance=obj)
30                  
31                  POST:
32                     form = Foo(instance=obj,dat=request.POST)
33                     ...
34                     form.save()
注意

使用

  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
  7 class UserInfoModelForm(forms.ModelForm):
  8 
  9     is_rmb = Ffields.CharField(widget=Fwidgets.CheckboxInput())  # 免登录Checkbox字段
 10 
 11     class Meta:
 12         model = models.UserInfo
 13         fields = '__all__'
 14         # fields =  ['username','email']
 15         # exclude = ['username']
 16         labels = {
 17             'username': '用户名',
 18             'email': '邮箱',
 19         }
 20         help_texts = {
 21             'username': '...'
 22         }
 23         widgets = {
 24             'username': Fwidgets.Textarea(attrs={'class': 'c1'})
 25         }
 26         error_messages = {
 27             '__all__':{            # 定义整体的错误信息
 28 
 29             },
 30             'email': {
 31                 'required': '邮箱不能为空',
 32                 'invalid': '邮箱格式错误..',
 33             }
 34         }
 35         field_classes = {
 36             # 'email': Ffields.URLField        # 和model中定义字段不同,这里只能填写类,可以覆盖model中的字段属性
 37         }
 38 
 39         # localized_fields=('ctime',)
 40 
 41     def clean_username(self):
 42         old = self.cleaned_data['username']
 43         return old
 44 
 45 class UserInfoForm(forms.Form):
 46     username = Ffields.CharField(max_length=32)
 47     email = Ffields.EmailField()
 48     user_type = Ffields.ChoiceField(
 49         choices=models.UserType.objects.values_list('id','caption')
 50     )
 51 
 52     def __init__(self, *args, **kwargs):
 53         super(UserInfoForm,self).__init__(*args, **kwargs)
 54         self.fields['user_type'].choices = models.UserType.objects.values_list('id','caption')
 55 '''
 56 源码截取: 
 57     def save(self, commit=True):
 58         if commit:
 59             # If committing, save the instance and the m2m data immediately.
 60             self.instance.save()
 61             self._save_m2m()
 62         else:
 63             # If not committing, add a method to the form to allow deferred
 64             # saving of m2m data.
 65             self.save_m2m = self._save_m2m
 66 '''
 67 
 68 def index(request):
 69     if request.method == "GET":
 70         obj = UserInfoModelForm()
 71         return render(request,'index.html',{'obj': obj})
 72     elif request.method == "POST":
 73         obj = UserInfoModelForm(request.POST)
 74         if obj.is_valid():
 75             # obj.save()
 76             instance = obj.save(False)            # self.instance 当前model对象
 77             instance.save()                        # 仅保存当前类对应的表,相当于源码中if条件的self.instance.save()
 78             obj.save_m2m()                        # 相当于源码中if条件的self._save_m2m(),else分支中做了赋值self.save_m2m = self._save_m2m
 79 
 80 
 81         # print(obj.is_valid())
 82         # print(obj.cleaned_data)
 83         # print(obj.errors.as_json())
 84         return render(request,'index.html',{'obj': obj})
 85 
 86 
 87 def user_list(request):
 88     li = models.UserInfo.objects.all().select_related('user_type')
 89     return render(request,'user_list.html',{'li': li})
 90 
 91 def user_edit(request, nid):
 92     # 获取当前id对象的用户信息
 93     
 94     if request.method == "GET":
 95         user_obj = models.UserInfo.objects.filter(id=nid).first()
 96         mf = UserInfoModelForm(instance=user_obj)            # 显示用户已经存在数据
 97         return render(request,'user_edit.html',{'mf': mf, 'nid': nid})
 98     elif request.method == 'POST':
 99         user_obj = models.UserInfo.objects.filter(id=nid).first()
100         mf = UserInfoModelForm(request.POST,instance=user_obj)
101         if mf.is_valid():
102 
103             mf.save()
104         else:
105             print(mf.errors.as_json())
106         return render(request,'user_edit.html',{'mf': mf, 'nid': nid})
107         
108 # modelform小结        
109     1. 生成HTML标签:class Meta: ...
110     2. 显示用户已经存在数据 :mf = xxxModelForm(instance=ModelObj)
111     3. 额外的标签, is_rmb = Ffields.CharField(widget=Fwidgets.CheckboxInput())  #  7天免登录Checkbox字段
112     4. 各种验证 is_valid() -> 各种钩子...  # 方法和Form中的钩子完全一样
113     5.     mf.save()
114         #
115         instance = mf.save(False)
116         instance.save()
117         mf.save_m2m()
原文地址:https://www.cnblogs.com/yum777/p/8904179.html