Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/298.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 动态更新ModelForm';s元类_Python_Django_Django Forms_Metaprogramming_Modelform - Fatal编程技术网

Python 动态更新ModelForm';s元类

Python 动态更新ModelForm';s元类,python,django,django-forms,metaprogramming,modelform,Python,Django,Django Forms,Metaprogramming,Modelform,我希望从我的视图中动态更新ModelForm的内联元类。尽管此代码似乎更新了Meta类中的排除列表,但是as_p(),as_ul()等的输出并不反映更新的Meta排除 然后,我假设html是在创建ModelForm时生成的,而不是在调用as_*()时生成的。有没有办法强制更新HTML 这是最好的方法吗?我只是认为这应该行得通 想法 from django.forms import ModelForm from testprogram.online_bookings.models import

我希望从我的视图中动态更新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 = []

元类用于动态构造表单定义-因此,在创建ModelForm实例时,排除中未包含的字段已添加为新对象的属性

通常的做法是为每个可能的排除列表定义多个类。但是,如果希望表单本身是动态的,则必须动态创建类定义。比如:

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'])

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


使用
modelform\u工厂
():


您可能应该使用{}.pop()而不是设置它然后删除它。exclude_list=kwargs.pop('exclude_list')保存一行代码。Shurgas@JustinAbrahms说我希望你可以使用kwargs.pop('exclude_list',默认值)类似于
exclude_list=kwargs.pop('exclude_list','')
jujule:当然,只要在表单函数中添加一个位置参数:“def PassengerForm(exclude_list,model,*args,**kwargs)”,并以设置Meta.exclude的相同方式设置Meta.model字段。例如,如果需要将实例传递给表单,则需要将
return MyPassengerForm()
替换为
return MyPassengerForm(*args,**kwargs)
。@DanielNaab-有趣。我确实想知道我是否走错了方向,但我必须添加
*args,**kwargs
,以便编辑现有实例;将
instance=object
传递到表单时,如果没有
*args,**kwargs
(无论如何,对我来说)@DanielNaab也许
get\u passenger\u form
PassengerForm
更符合代码其余部分的样式
PassengerForm
看起来像是一个类,但实际上是一个method@Erve1879对我来说,只有在传递实例时返回
MyPassengerForm(*args,**kwargs)
时,它才起作用。我认为原因是,
args
kwargs
被分配到上面的
MyPassengerForm
范围之外,因此当它被实例化为
MyPassengerForm()
时,
args
kwargs
不包含任何内容。
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)
from django.forms.models import modelform_factory

from testprogram.online_bookings.models import Passenger

exclude = ('field1', 'field2')
CustomForm = modelform_factory(model=Passenger, exclude=exclude)  # generates ModelForm dynamically
custom_form = CustomForm(data=request.POST, ...)  # form instance