• Python 统一动态创建多个model对应的modelForm类(type()函数)


    一、ModelForm的用法

    ModelForm对用户提交的数据有验证功能,但比Form要简单的多

    from django.forms import ModelForm # 导入ModelFormclass
    customerModelForm(ModelForm):
        class Meta:
            model=models.UserInfo
            fields="__all__"
            labels={
                'name':'用户名',
                'password':'密码',
                'qq':'qq号',
                '微信':'微信号',
                'roles':'角色'
            }

    说明:

      1.model:对应得表名

      2.fields:选择字段列表,'__all__'是选择所有字段

      3.exclude:排除字段列表

      4.widgets:插件列表

      5.labels:前端显示字段名

      6.error_messages:自定义错误提示

      7.localized_field:本地化,如:根据不同时区显示数据

    除了这些参数,ModelForm和Form一样可以定义局部钩子和全局钩子

    2.实例化表单对象,传入模板,同Form

    model_form = customerModelForm()
    return render(request,"index.html",{"model_form":model_form})

    3、前端通过传递的model_form展示

    <div class="row">
    {{ model_form.errors }}
    <form class="form-horizontal" method="post" >
    {% csrf_token %}
    {% for field in model_form %}
    <div class="form-group">
    <label class="col-sm-2 " style="font-weight: normal">
    {% if field.field.required %}
    <b> {{ field.label }} (*必填项) </b>
    {% else %}
    {{ field.label }}
    {% endif %}
    </label>
    <div class="col-sm-10">
    <span style="color: red;">{{ field.errors }}</span>
    {{ field }}
    </div>
    </div>
    {% endfor %}
    </form>
    </div>

    4、form提交后,后端view通过以下方式,验证提交的表单

    model_form = customerModelForm(request.POST)
    if model_form.is_valid():
        model_form.save()

    5.如果是修改记录,则需要传入记录对象

    obj = customerModel.objects.get(id=obj_id) #查到原来的值
    model_form = customerModelForm(instance=user_obj) #传入值
    model_form = customerModelForm(request.POST, instance=obj) #将原来的值生成新值
    if model_form.is_valid():
        model_form.save()
     
     

     

    二、有多个Model,不想要每个model写一个ModelForm的,采用动态生成ModelForm类的方法

    A、动态生成类的函数:type('classname',(object,),dict(funname=fun))

    参数:

    1、class的名称,字符串形式;

    2、继承的父类集合,注意Python支持多重继承,如果只有一个父类,注意tuple的单元素写法;

    3、class的方法名称与函数绑定,这里我们把函数fun绑定到方法名funname上,可以采用:

    setattr(classname,"funname",fun)方式替代

    例子:
    def CreateModelForm(request,admin_obj):
    class Meta:
    model = admin_obj.model
    fields = "__all__"

    def __new__(cls, *args, **kwargs):
    for field_name,field_obj in cls.base_fields.items():
    field_obj.widget.attrs['class'] = 'form-control'
    if field_name in admin_obj.readonly_fields:
    field_obj.widget.attrs['disabled'] = True #在后台不能通过这种方式修改外键对应的字段,比如consultant
    return forms.ModelForm.__new__(cls)

    def default_clean(self):
    print("cleaned data:",self.cleaned_data)

    dynamic_model_form = type("DynamicModelForm",(forms.ModelForm,), {"Meta":Meta})
    setattr(dynamic_model_form,"__new__",__new__)
    setattr(dynamic_model_form,"clean",default_clean)
    return dynamic_model_form

    上述例子就可以根据需求动态生成dynamic_model_form了,需要使用的时候调用CreateModelForm函数即可
    model_form = forms.CreateModelForm(request,admin_obj=admin_obj)





  • 相关阅读:
    Eclipse Alt + / 快捷键失效
    oracle nvl()函数
    搭建spring boot项目
    Maximum call stack size exceeded
    vue混入函数问题
    ASP.NET Core 2.0中的Azure Blob存储
    如何在ASP.NET Core 2.0中使用Razor页面
    将参数传递给ASP.NET Core 2.0中的中间件
    使用.net core在Ubuntu构建一个TCP服务器
    如何在ASP.NET Core Web API测试中使用Postman
  • 原文地址:https://www.cnblogs.com/yoyo008/p/9141380.html
Copyright © 2020-2023  润新知