• 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的另一个例子
  • 相关阅读:
    Visual Studio 2010 Ultimate敏捷利剑:详解Scrum
    Microsoft .Net Micro Framework 3.0 and BIC Survey(2008 WinHEC)
    Visual Studio 2010 Ultimate开发与测试敏捷特性
    博客园开发征途又添新书《.NET软件设计新思维——像搭积木一样搭建软件》出版
    《运用Microsoft Visual Studio 2010落实敏捷软件开发》CSDN大会我的Session(PPT已上传)
    北京微软.Net和博客园俱乐部Open Party两本新书交流活动(已圆满结束)
    使用ASP.Net 3.5 的Ajax与Web服务开发实例
    WCF服务在JavaScript中使用ASP.NET的AJAX方法
    浅谈MVP与ModelViewViewModel(MVVM)设计模式
    荣获“微软2009最有影响力开发者”称号
  • 原文地址:https://www.cnblogs.com/ray-h/p/10415269.html
Copyright © 2020-2023  润新知