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吗?
答案 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()