0

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

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

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

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

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

支付系统.py:

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

表格.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)
4

1 回答 1

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

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

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

fields是一个dict(或者我猜 -OrderedDict就此而言)并且要删除字段,您需要删除整个键值映射。

于 2013-11-11T20:49:19.807 回答