如何动态修改django widget参数?

时间:2013-03-28 09:41:06

标签: python django

让我说我有这样一种形式:

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小部件呈现,而不仅仅是相关的字段值?

1 个答案:

答案 0 :(得分:2)

因为您要更改form.base_fields,这是由该类的所有实例共享的。不要这样做,请更改form.fields,这是特定于实例的。

作为一种风格问题,我更喜欢在表单本身的__init__方法中执行此操作,并将URL参数作为表单kwarg传递 - 看起来您可以覆盖视图的{{1}方法来做到这一点,那么你根本不需要改变get_form_kwargs