Django之ModelForm使用

Posted ray-h

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django之ModelForm使用相关的知识,希望对你有一定的参考价值。

一:什么是ModelForm呢?

Model + Form ==> ModelForm。model和form的结合体,所以有以下功能:

  • 数据验证
  • 数据库操作

model有操作数据库的字段,form验证也有那几个字段,虽然耦合度降低,但是代码是有重复的。如果利用model里的字段,那是不是form里的字段就不用写了。

二:下面是一个简单是例子:
技术图片
from django.db import models

class CustomerInfo(models.Model):
    """客户表"""
    name = models.CharField(max_length=64)
    contact_type_choices = ((0,QQ),(1,微信),(2,手机))
    contact_type = models.SmallIntegerField(choices=contact_type_choices)
    contact = models.CharField(max_length=64,unique=True,verbose_name="联系方式")
    source_choices = ((0,QQ群),(1,51CTO),(2,百度推广),(3,知乎),(4,转介绍),(5,其它))
    source = models.SmallIntegerField(choices=source_choices,verbose_name="客户来源")
    referral_from = models.ForeignKey("self",blank=True,null=True,verbose_name="转介绍",on_delete=models.CASCADE)
    consult_courses = models.ManyToManyField("Course",verbose_name="咨询课程")
    consult_content = models.TextField(verbose_name="咨询内容")
    status_choices = ((0, 未报名), (1, 已报名), (2, 已退学))
    status = models.SmallIntegerField(choices=status_choices,verbose_name="状态")
    consultant = models.ForeignKey("UserProfile",verbose_name="课程顾问",on_delete=models.CASCADE)
    date = models.DateField(auto_now_add=True)
    def __str__(self):
        return self.name
models.py
技术图片
from django.forms import ModelForm
from crm import models
from django import forms

class CustomerForm(ModelForm):
    class Meta:
        model = models.CustomerInfo
        fields = __all__
        exclude = [consult_content, status, consult_courses]
        readonly_fields = [contact_type,contact,consultant,referral_from,source]   #并不是真正的设置可读模式,而是用于自定制

    def __new__(cls, *args, **kwargs):      # cls 就是实例(self)
        for field_name in cls.base_fields:
            field_obj = cls.base_fields[field_name]
            field_obj.widget.attrs.update({class:form-control})
            if field_name in cls.Meta.readonly_fields:
                field_obj.widget.attrs.update({disabled:true})
                # print(cls.Meta)
        # print(cls.Meta.exclude)
        return ModelForm.__new__(cls)

    def clean(self):
        """对数据进行验证,此方法需要在form.is_valid()后才能生效"""
        # print("cleaned_dtat:", self.cleaned_data)
        if self.errors:  # 表单级别的错误
            raise forms.ValidationError(("Please fix errors before re-submit."))
        for field in self.Meta.readonly_fields:
            old_field_val = getattr(self.instance,field)
            new_form_val = self.cleaned_data[field]
            if old_field_val != new_form_val:
                self.add_error(field,"Readonly Field: field should be ‘{value}‘ ,not ‘{new_value}‘ ".                                         format(**{value:old_field_val,new_value:new_form_val}))
forms
技术图片
def enrollment(request,enrollment_id):
    """②学员确认信息"""
    customer_form = forms.CustomerForm(instance=enrollment_obj.customer)
    
    if request.method == "POST":
        customer_form = forms.CustomerForm(instance=enrollment_obj.customer,data=request.POST)
        if customer_form.is_valid():
            customer_form.save()
            return HttpResponse(合同正在审核中,请等候...)

    return render(request,crm/enrollment.html,locals())
views

注意我们如何在POST和GET情况下传递实例(instance)。

 

三、Meta的作用:

  • ModelForm 通过 Meta 把 db.Field 自动转化为 forms.Field,其中涉及到几步转化
  • validators 不变
  • 添加 widget 属性,即前端的渲染方式
  • 修改 Model 包含的字段,通过 fields 来拿指定字段或者通过 exclude 来排除指定字段
  • 修改错误信息
技术图片
class Meta:
        model = models.UserInfo
        fields = __all__
        # fields =  [username,email]
        # exclude = [username]
        labels = {
            username: 用户名,
            email: 邮箱,
        }
        help_texts = {
            username: ...
        }
        widgets = {
            username: Fwidgets.Textarea(attrs={class: c1})
        }
        error_messages = {
            __all__:{
 
            },
            email: {
                required: 邮箱不能为空,
                invalid: 邮箱格式错误..,
            }
        }
        field_classes = {
            # email: Ffields.URLField
        }
 
        # localized_fields=(ctime,)
Meta的另一个例子

 

 

 

以上是关于Django之ModelForm使用的主要内容,如果未能解决你的问题,请参考以下文章

Django之modelform组件

Django之ModelForm详解

Django之ModelForm组件

django之ModelForm组件

Django之modelform

Django之ModelForm