在实例化之前更改django表单类

时间:2013-11-11 20:26:46

标签: python django django-forms

我想知道在实例化之前是否可以更改或更改表单类。

作为一个具体的例子,我有一个付款表格,需要根据使用的付款系统进行修改。

理想情况下,我宁愿不创建不同的表单类,然后根据支付系统选择不同的表单类;相反,支付系统对象将“告诉”表单类需要进行哪些更改 - 例如,使某些字段可选或指示它们使用不同的小部件。

这可能吗?另一种方法是将表示支付系统的对象传递给表单,然后让它在实例化后修改表单,但是在某种程度上让它在表单类而不是视图中运行似乎很笨拙。我觉得Django“视图”更接近控制器,似乎这就是这样的事情应该发生的地方。我也觉得修改它最好修改form_class对象而不是表单实例;我甚至不确定在这样的事实之后添加字段时它是否会正确处理验证和表单填写。会吗?

在任何地方,这里有一些示例代码,说明如何将付款对象传递给表单实例化调用:

payment_system.py:

class ExamplePaymentSystem(BasePaymentSystem):
    def modify_form(self, form):
        for fld in self.optional_fields:
            form.fields[fld].required = False
        …etc…

forms.py:

class ModifiablePaymentForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        self.payment_system = kwargs.pop("payment_system", None)
        super(ModifiablePaymentSystem, self).__init__(*args, **kwargs)
        self.payment_system.modify_form(self)

1 个答案:

答案 0 :(得分:3)

您不应该修改全局静态数据(在模块范围定义的类是静态的),因为如果您在每个进程的许多线程中运行代码(通常这样做),一个线程可能会修改其他线程使用的表单类。

如果您的支付系统是静态的(您没有动态添加新服务器,而服务器正在运行)我会为每个支付系统定义一个表单。

如果没有,您可以随时定义新的表单类型:

 def get_form_type(payment_system): 
    class DynamicForm(BasePaymentForm): 
        ... add change fields etc... 
    return DynamicForm

或修改类似的实例:

class PaymentForm(BasePaymentForm): 

     def __init__(self, ..., payment_system):
         self.fields['foo'].required = False # <--- I'm writing code 
         #from the memory, so possibly you'll need t edit it 
         #but this is doable and easy to do. 

如何删除表单中的字段(每个OP请求)。

当你继承:

这很难,我认为您需要浏览表单内部并在创建子类后手动修改它们。 这是一个疯狂的猜测......

 def get_form_type(payment_system): 
    class DynamicForm(BasePaymentForm): 
        ... add change fields etc... 
    del DynamicForm.base_fields['foo']
    return DynamicForm

修改实例时: 我不是百分百肯定,但我偷看了django源代码(不幸的是这些细节不在文档中)。但我想你应该:

 class PaymentForm(BasePaymentForm): 
     def __init__(self, ..., payment_system):
         del self.fields['foo']

fieldsdict(或者我想 - OrderedDict就此而言)并删除字段,您需要删除整个key-vaule映射。