【问题标题】:Python/Django Forms: Dynamic variable creation and access for Form fieldsPython/Django 表单:表单字段的动态变量创建和访问
【发布时间】:2013-04-03 14:17:00
【问题描述】:

我有一个只有一个小部件的 django 表单类。我想给这个小部件起一个名字,比如<select name="custom_name"></select>,但 Django 采用变量的名称并将其作为小部件的名称。例如:

class MultiSelectForm(forms.Form):
    here_is_the_name_of_the_widget = forms.MultipleChoiceField()

所以上面的代码会创建一个有名字的小部件:

<select name="here_is_the_name_of_the_widget">...</select>

因为我需要在初始化时创建此名称所需的表单原型。 在此之前,此表单工作正常,但具有标准的预先给定的名称:

class MultiSelectForm(forms.Form):
    multiple_select = forms.MultipleChoiceField()

    def __init__(self, attrs=None, choices=(), *args, **kwargs):            
        self.base_fields['multiple_select'].choices = choices
        self.base_fields['multiple_select'].empty_permitted = False
        self.base_fields['multiple_select'].required = kwargs.get('required', False)
        self.base_fields['multiple_select'].widget = MultiSelect(attrs=attrs, choices=choices)

        forms.Form.__init__(self, *args, **kwargs)

所以,我想了一种方法(黑客)来实现我想要的,但没有按我预期的那样工作。如果我想给小部件起的名称是“国家”,则会产生以下错误:

KeyError at <project_name>
'countries'

产生该错误的代码是:

class MultiSelectForm(forms.Form):
    multiple_select = forms.MultipleChoiceField()

    def __init__(self, attrs=None, choices=(), *args, **kwargs):
        default_name = 'multiple_select'

        name = attrs.get('name', default_name)
        if name != default_name:
            setattr(self, name, forms.MultipleChoiceField())
            del attrs['name']

        '''
        The error is produced in the following line...
        '''
        self.base_fields[str(name)].choices = choices
        self.base_fields[str(name)].empty_permitted = False
        self.base_fields[str(name)].required = kwargs.get('required', False)
        self.base_fields[str(name)].widget = MultiSelect(attrs=attrs, choices=choices)

        forms.Form.__init__(self, *args, **kwargs)

有没有办法实现这一点,或者更好的方法?

谢谢!

这里是解决方案...

感谢@Daniel Roseman

class MultiSelectForm(forms.Form):
    def __init__(self, attrs=None, choices=(), *args, **kwargs):
        #empty_permitted is a Form's attribute
        kwargs['empty_permitted'] = False
        forms.Form.__init__(self, *args, **kwargs)

        name = attrs.get('name', 'multiple_select')
        self.fields[name] = forms.MultipleChoiceField(
            choices=choices,
            required=kwargs.get('required', False),
            widget=MultiSelect(attrs=attrs, choices=choices)
            )

【问题讨论】:

    标签: python variables dynamic django-forms django-widget


    【解决方案1】:

    我完全不知道你为什么需要这样做,但你肯定是把事情复杂化了。您可以在实例化时将字段动态添加到表单中:

    class MultiSelectForm(forms.Form):
        def __init__(self, *args, **kwargs):
            dynamic_field = kwargs.pop('dynamic_field')
            super(MultiSelectForm, self).__init__(*args, **kwargs)
            self.fields[dynamic_field['name']] = forms.MultipleChoiceField(
                choices=dynamic_field['choices'], 
                empty_permitted=False
                required=dynamic_field['required'],
                widget=MultiSelect(attrs=dynamic_field['attrs']))
    

    然后在实例化时传递一个字典:

    my_form = MultiSelectForm(
        dynamic_field={'name': 'countries', 'choices': (mychoices), 'required': True})
    

    【讨论】:

      猜你喜欢
      • 2011-01-24
      • 2012-02-22
      • 2011-03-22
      • 2019-05-05
      • 2013-04-04
      • 1970-01-01
      • 2021-03-10
      • 2017-08-10
      • 2016-11-11
      相关资源
      最近更新 更多