Python学习笔记Day25 - Django_ModelForm

ModelForm

model和form的结合体,比form方便,但是耦合太强,不适合大规模
参考博客

Model + Form => 验证 + 数据库操作

利用model.A中的字段,不用重复再写字段

创建ModelForm

from django import forms
from django.forms import widgets as Fwidgets
class UserInfoModelForm(forms.ModelForm):

is_rmb = Ffields.CharField(widget=Fwidgets.CheckboxInput()) # 创建model以外的标签,用法同form的Field

class Meta: # 创建model已有的字段标签
model = models.UserInfo
fields = 'all'

def clean_username(self):
old = self.cleaned_data['username']
return old

./views.py
obj = XXOOModelForm(request.POST) # 提交数据
if obj.is_valid():
obj = form.save() # 默认自动保存多对多数据
else:
print(obj.errors['user'][0]) # 获取指定错误信息
print(obj.errors.as_json()) # 打包为字典的错误信息

./xxx.html

{{ obj.user }} {{ obj.user.errors }}

{{ obj.as_p }} {{ obj.user.errors }} # 一次性以

生成所有标签
{{ obj.as_ul }} {{ obj.user.errors }} # 一次性以

    生成所有标签


    {{ obj.as_table }} {{ obj.user.errors }} # 一次性以
    生成所有标签

    {{ form.xxoo.label }} # label值
    {{ form.xxoo.id_for_label }} # label的for值,id_xxx
    {{ form.xxoo.label_tag }} # 自动生成label(包含上述两点)
    {{ form.xxoo.errors }} # 错误信息

    Meta字段

    class Meta: # 生成HTML标签
    model = models.UserInfo -> 对应的Model
    fields=None -> 字段, 'all' => 所有字段, ['username','email']
    exclude=None -> 排除字段, ['username']
    labels=None -> 提示信息, {'username':'用户名'}
    help_texts=None -> 帮助提示信息, {'username':'用户名不能以数字开头...'}
    widgets=None -> 自定义插件, {'username':F_widgets...}
    => 需要从Form里导入widgets并 as ...重命名,以免和字段名重复
    error_messages=None -> 自定义错误信息, {'username':{'required':'不能为空'},'email':{...}}
    => 可整体定义错误信息 {'all':{...}}
    # ? from django.core.exceptions import NON_FIELD_ERRORS
    field_classes=None -> 自定义字段类型 (将model中定义的字段类型修改)
    => {'email':F_field.URLField}
    localized_fields=None -> 本地化,如:根据不同时区显示数据, =('birth_date',)
    # 如:
    数据库中,默认UTC时间
    2016-12-27 04:10:57
    需要在setting中做相应的配置
    TIME_ZONE = 'Asia/Shanghai'
    USE_TZ = True
    则显示:
    2016-12-27 12:10:57

    article_modelform = ArticleModelForm(label_suffix='') -> 修改label后缀

    创建或修改数据

    .../views.py

    obj = XXOOModelForm() # 页面显示
    模板文件中的使用类似Form

    obj = XXOOModelForm(request.POST) # 提交数据
    if obj.is_valid():
    obj = form.save() # 默认自动保存多对多数据
    values = obj.cleaned_data # 获取正确数据
    return ...
    else:
    print(obj.errors.as_json())
    return ...

    拆分为三步

    obj = form.save(commit=False)
    obj.save() # 保存单表信息
    obj.save_m2m() # 保存关联的多对多信息

    更新和初始化数据

    • 修改数据GET时,传入原始数据

      obj = model.tb.objects.get(id=1) # 从model中获取对象
      model_form_obj = XXOOModelForm(instance=obj) # GET时,将obj对象作为默认值传给modelFrom显示

    • 修改完POST时,将数据更新至当前对象,否则将新建数据而不是更新数据

      obj = model.tb.objects.get(id=1)
      model_form_obj = XXOOModelForm(request.POST,instance=obj) # POST时,将提交的数据更新至obj对象

    PS: 单纯初始化

    model_form_obj = XXOOModelForm(initial={...})

    修改样式属性

    • 第一种方法:

      class BookForm(forms.ModelForm):
      class Meta:
      ...
      widgets = {
      'name': Textarea(attrs={'cols': 80, 'rows': 20}),
      'description': Textarea(attrs={'cols': 80, 'rows': 20}),
      }

    • 第二种重写__init__方法:

      class BookForm(forms.ModelForm):
      class Meta:
      model = Book
      def init(self, args, **kwargs):
      super().init(
      args, **kwargs)
      self.fields['name'].widget.attrs.update({'class': 'special'})
      self.fields['description'].widget.attrs.update(size='40')

    验证的执行过程

    UserForm >>继承>> Form >>>>>>>>>>>>>>>>>>>>>>>>>>>>>继承>> BaseForm(is_valid...)

    UserModelForm >>继承>> ModelForm >>继承>> BaseModelForm >>继承>> BaseForm

    ModelForm验证的使用方法与Form一样

    is_valid -> full_clean -> 钩子 -> 整体错误

    字典字段验证

    def clean_字段名(self):
    # 可以抛出异常
    # from django.core.exceptions import ValidationError
    return "新值"

    用于验证

    obj = XXOOModelForm()
    obj.is_valid()
    obj.errors.as_json()
    obj.clean()
    obj.cleaned_data

    Django ModelChoiceField前台下拉菜单显示object的解决方法

    在model中添加如下代码即可,不加的话显示就是object

    def str(self):
    return self.name

    隐藏的modelform标签,而如果该标签为required,提交时浏览器会报错

    解决办法:

    1. form表单添加novalidate属性,但会导致所有验证都不能用,不建议

    2. 取消该标签的required

posted @ 2020-07-05 23:36  Jerome12138  阅读(155)  评论(0)    收藏  举报