Django Form-动态切换字段存在

时间:2018-12-11 19:18:18

标签: python django race-condition

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字典?

2)是否有更好的解决方案来解决此问题,而不是对base_fields执行pop / del?

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

1 个答案:

答案 0 :(得分:3)

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()