Django Form - 动态切换字段存在

Django Form - toggle field existence dynamically

Python 2.7.8 和 Django==1.4.2(旧版应用)

几个月前,我在调查 Django 项目中的错误时遇到了一个令人困惑的问题。我相信这与 Django 线程池的方式有关,但很难确定。这是重现此问题的最小可行示例:

class FormA(Form):
    field_a = CharField()

    def __init__(self, *args, **kwargs):
        if kwargs['initial']['test']:
            self.base_fields['field_b'] = CharField()
        super(FormA, self).__init__(*args, **kwargs)

class ViewA(FormView):
    template_name = 'test'
    form_class = FormA

    def get_initial(self):
        initial = super(ViewA, self).get_initial()
        initial['test'] = self.request.GET.get('test')

当根据查询参数动态添加新字段时,如果首先发出查询参数 test 评估为 True 的请求,field_b 将包含在 FormA 中。但是,我怀疑对于所有连续的请求(即使 test 评估为 False),FormA 保留 field_b.

解决方法是从 self.base_fields 中弹出或删除 field_b,然后计算测试变量。这行得通,但我不完全确定为什么需要它。

def __init__(self, *args, **kwargs):
    self.base_fields.pop('field_b', 0)
    if kwargs['initial']['test']:
        self.base_fields['field_b'] = CharField()
    super(FormA, self).__init__(*args, **kwargs)

似乎 base_fields 字典在多个请求中持续存在。所以这引发了以下问题:

1) 为什么 base_fields dict 没有在每次请求时重新初始化?

2) 除了在 base_fields 上执行 pop/del 之外,是否有更好的解决方案来解决此问题?

3) 如果没有其他解决方案,pop/del 是否会导致竞争条件?如果同时发出两个请求怎么办---一个请求是否会弄乱另一个请求的base_fields?

如前所述here,您不应修改实例的base_fields

解决方法:

class FormA(Form):
    field_a = CharField()

    def __init__(self, *args, **kwargs):

        # this will populate `self.fields`
        super(FormA, self).__init__(*args, **kwargs)

        if kwargs['initial']['test']:
            self.fields['field_b'] = CharField()