动态更新ModelForm的元类

2024-09-28 20:52:02 发布

您现在位置:Python中文网/ 问答频道 /正文

我希望从我的视图中动态更新ModelForm的内联元类。尽管这段代码似乎更新了Meta类中的排除列表,但是来自as_p()as_ul()等的输出并不反映更新后的Meta排除。

我假设html是在创建ModelForm时生成的,而不是在调用as_*()时生成的。有没有办法强制更新HTML?

这是最好的方法吗?我只是认为这个应该有效。

有什么想法?

from django.forms import ModelForm

from testprogram.online_bookings.models import Passenger

class PassengerInfoForm(ModelForm):

    def set_form_excludes(self, exclude_list):
        self.Meta.exclude = excludes_list

    class Meta:
        model = Passenger
        exclude = []

Tags: 代码fromimportself视图列表as动态
3条回答

Meta类用于动态构造表单定义,因此在创建ModelForm实例时,不在exclude中的字段已经作为新对象的属性添加。

通常的方法是为每个可能的排除列表都有多个类定义。但如果希望窗体本身是动态的,则必须动态创建类定义。类似于:

def get_form(exclude_list):
    class MyForm(ModelForm):
        class Meta:
            model = Passenger
            exclude = exclude_list
    return MyForm

form_class = get_form(('field1', 'field2'))
form = form_class()

更新:我刚刚回顾了这篇文章,并认为我会发布一个更习惯的方法来处理动态类:

def PassengerForm(exclude_list, *args, **kwargs):
    class MyPassengerForm(ModelForm):
        class Meta:
            model = Passenger
            exclude = exclude_list

        def __init__(self):
            super(MyPassengerForm, self).__init__(*args, **kwargs)

    return MyPassengerForm()

form = PassengerForm(('field1', 'field2'))

另一种方式:

class PassengerInfoForm(ModelForm):
    def __init__(self, *args, **kwargs):
        exclude_list=kwargs.pop('exclude_list', '')

        super(PassengerInfoForm, self).__init__(*args, **kwargs)

        for field in exclude_list:
            del self.fields[field]

    class Meta:
        model = Passenger

form = PassengerInfoForm(exclude_list=['field1', 'field2'])

类似的方法,有点不同的目标(任意模型的通用模型形式):

from django.contrib.admin.widgets import AdminDateWidget
from django.forms import ModelForm
from django.db import models

def ModelFormFactory(some_model, *args, **kwargs):
    """
    Create a ModelForm for some_model
    """
    widdict = {}
    # set some widgets for special fields
    for field in some_model._meta.local_fields:
        if type(field) is models.DateField:
            widdict[field.name] = AdminDateWidget()

    class MyModelForm(ModelForm): # I use my personal BaseModelForm as parent
        class Meta:
            model = some_model
            widgets = widdict

    return MyModelForm(*args, **kwargs)

相关问题 更多 >