【问题标题】:Django custom ModelForm metaclass, "object has no attribute '_meta'"Django 自定义 ModelForm 元类,“对象没有属性 '_meta'”
【发布时间】:2019-04-15 23:27:15
【问题描述】:

我正在尝试创建一个自定义的 Django ModelForm 元类,它允许对从源模型继承的表单字段进行一些额外的自定义,例如:

  • 将选项限制为可用于特定模型字段的所有选项的子集
  • 定义只读和必填的表单字段
  • 为字段设置初始值

我这样做是因为我需要几个不同的 ModelForms 用于单个模型,每个模型都有上述选项的变体。这是我的元类:

class CustomModelFormMetaclass(models.ModelFormMetaclass):
"""
Custom ModelForm metaclass which adds extra configuration of fields inherited from Model
"""
def __new__(mcs, name, bases, attrs):
    new_class = super(models.ModelFormMetaclass, mcs).__new__(mcs, name, bases, attrs)
    # Set initial field values
    #initials = attrs.get('initial_values')
    for field_name, initial_value in new_class.initial_values.items():
        field = new_class.base_fields.get(field_name, None)
        if field and field.initial is None:
            field.initial = initial_value

    # Set refined choices
    #refined_choices = attrs.get('refined_choices')
    for field_name, refined_choices in new_class.refined_choices.items():
        set_field_choices(new_class, field_name,refined_choices)

    # Set disabled fields
    for field_name in new_class.read_only_fields:
        field = new_class.base_fields.get(field_name, None)
        if field:
            #field.disabled=True
            field.widget.attrs['readonly'] = True

    # Set required fields
    for field_name in new_class.required_fields:
        field = new_class.base_fields.get(field_name, None)
        if field:
            field.required=True

    # Set DateTime and Date help texts
    for field in new_class.base_fields.values():
        if field.help_text is None:
            if type(field).__name__ == 'DateTimeField':
                field.help_text = 'YYYY-MM-DD HH:MM:SS'
            elif type(field).__name__ == 'DateField':
                field.help_text = 'YYYY-MM-DD'

    return new_class

以及将成为实际 ModelForms 父类的基本自定义 ModelForm 类:

class CustomModelForm(forms.BaseModelForm, metaclass=CustomModelFormMetaclass):
method='post'
target=None
target_params={}

refined_choices={}

initial_values={}

read_only_fields=[]

required_fields= []

一个这样的例子是(这个例子没有利用我的自定义参数):

class LBSListAdminForm(darwin_forms.CustomModelForm):
method = 'get'

class Meta:
    model = LBSListRequest
    exclude = ['start_time', 'site', 'process_id', 'user', 'duration', 'method', 'request_data', 'status', 'response']
    labels = {}
    help_texts = {}
    error_messages = {}
    widgets = {}

但是我收到了这个错误:

“LBSListAdminForm”对象没有属性“_meta”

我在这里做错了什么?具有多级继承的metclass 链越来越混乱。感谢任何帮助

干杯

【问题讨论】:

    标签: python django django-models django-forms modelform


    【解决方案1】:

    _meta 属性由__new__ 中的ModelFormMetaclass 设置。问题是您没有在子类中正确调用super(),因此在ModelFormMetaclass 中没有调用__new__,因此没有设置_meta

    super() 的调用应将当前类作为其第一个参数,因此应为:

    new_class = super(models.CustomModelFormMetaclass, mcs).__new__(mcs, name, bases, attrs)
    

    【讨论】:

    • 谢谢,愚蠢的我,我从基类复制了超级行
    猜你喜欢
    • 1970-01-01
    • 2021-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 2018-05-07
    • 2019-10-21
    • 1970-01-01
    相关资源
    最近更新 更多