让我说我有这样一种形式:
class ChangeParentCIForm(ModelForm):
class Meta:
model = CINodeInventory
fields = ('parent',)
widgets = {'parent': AutocompleteWidget('inventory.uuid'),}
问题在于,在我的情况下,AutocompleteWidget内容不仅必须是'父'字段值的上下文,还必须是用户会话信息(对我来说是用户在另一页上选择的数据库版本号)
为此,我在基于类的视图中做了类似的事情:
class CompanyManageChangeParentCIView(CompanySelectedMixin,CIContextMixin,CompanyViewCIMixin,UpdateView):
template_name = 'inventory/browse_change_parent_ci.html'
context_object_name = 'ci'
form_class = ChangeParentCIForm
def get_form(self,form_class):
form = super(CompanyManageChangeParentCIView,self).get_form(form_class)
form.base_fields['parent'].widget.url_params={'version':self.request.session['use_version']}
return form
当然,我修改了AutocompleteWidget代码来处理这个'url_params'额外参数。
它可以工作,但是这个代码在我看来并不是很漂亮,因为它修改了在初始时为一个也在初始时生成的字段创建的小部件。 如果你创建了2个表单实例,它会指向相同的字段和小部件,所以如果我这样做:
def get_form(self,form_class):
form1 = super(CompanyManageChangeParentCIView,self).get_form(form_class)
form2 = super(CompanyManageChangeParentCIView,self).get_form(form_class)
form1.base_fields['parent'].widget.url_params="val1"
form2.base_fields['parent'].widget.url_params="val2"
print id(form1),id(form1.base_fields['parent'].widget)
print id(form2),id(form2.base_fields['parent'].widget)
可以看到form1和form2是针对不同的实例,但是它们指向相同的小部件(如果打印它们的id,则指向相同的字段)。所以对我来说,如果我将form1和form2显示在同一个模板中,我将显示2个小部件“AutocompleteWidget”,但都是使用最新修改自定义的,即url_parms =“val2”
即使我显示一个表单,在我看来非常危险,如果2个线程正在为同一个小部件执行相同的代码和2个不同的“url_params”值,会发生什么?
所以这是我的问题:如何使用上下文信息自定义django小部件呈现,而不仅仅是相关的字段值?
答案 0 :(得分:2)
因为您要更改form.base_fields
,这是由该类的所有实例共享的。不要这样做,请更改form.fields
,这是特定于实例的。
作为一种风格问题,我更喜欢在表单本身的__init__
方法中执行此操作,并将URL参数作为表单kwarg传递 - 看起来您可以覆盖视图的{{1}方法来做到这一点,那么你根本不需要改变get_form_kwargs
。