【问题标题】:Pass parameter to Form in Django将参数传递给 Django 中的表单
【发布时间】:2011-08-31 14:53:33
【问题描述】:

我有一个自定义表单,我想向其传递一个参数。 在this 示例之后,我想出了以下代码:

class EpisodeCreateForm(forms.Form):
    def __init__(self, *args, **kwargs):
        my_arg = kwargs.pop('my_arg')
        super(EpisodeCreateForm, self).__init__(*args, **kwargs)

    my_field = forms.CharField(initial=my_arg)

但我收到以下错误:

Exception Value: name 'my_arg' is not defined

如何让它识别表单代码中的参数?

【问题讨论】:

    标签: django django-forms


    【解决方案1】:

    需要参考__init__中的表单域实例来设置初始值。要访问__init__ 中的表单字段实例,请将其放在对super 的调用之前:

    self.fields['my_field'].initial=my_arg
    

    并从您声明 my_field 的位置删除 initial=my_arg,因为此时(声明类时)my_arg 不在范围内。

    【讨论】:

    • 它不知道属性字段,这正常吗?如果我以后想在表单的 save 方法中使用这个参数呢?
    • 我搞砸了——对 super 的调用需要在 self.fields 之前进行,否则它将不存在。
    • 酷,这行得通!如果我想在表单的保存方法中使用这个变量怎么办?
    • 好吧,我想我可以在这样的隐藏字段中传递它。这行得通。无论如何谢谢:)
    【解决方案2】:

    问题是my_field 在创建类时初始化,但my_arg 在创建新实例时初始化,my_field 知道它的值为时已晚。你可以做的是在__init__中初始化my_field

    def __init__(self, *args, **kwargs):
        my_arg = kwargs.pop('my_arg')
        super(EpisodeCreateForm, self).__init__(*args, **kwargs)
        if not self.my_field:
            self.my_field = my_arg
    

    【讨论】:

    • 如果我在它出现的两个地方都用 self.my_arg 替换 my_arg,那么它告诉我它不知道 self..
    • 我无法让它初始化 init 方法中的字段。如果我在 init 方法中声明表单字段,它就不会显示出来。
    • @Johanna 在super(...) 函数调用之后执行此操作
    【解决方案3】:

    此代码在导入时执行一次:

    my_field = forms.CharField(initial=my_arg)
    

    并且此代码在表单实例创建时执行:

    my_arg = kwargs.pop('my_arg')
    super(EpisodeCreateForm, self).__init__(*args, **kwargs)
    

    所以这不会以这种方式工作。您应该在 __init__ 方法中为该字段设置初始值。

    顺便说一句,这一切似乎都没有必要,为什么不在视图中使用'initial'关键字呢?

    【讨论】:

    • 如何在视图中使用初始关键字?
    【解决方案4】:

    考虑到您的评论,我会这样做:

    class EpisodeCreateForm(forms.Form):
        def __init__(self, *args, **kwargs):
            self.my_arg = kwargs.pop('my_arg')
            kwargs.setdefault('initial', {})['my_field'] = self.my_arg
            super(EpisodeCreateForm, self).__init__(*args, **kwargs)
    
        def save(self):
            do_something(self.my_arg)
            ...
            super(EpisodeCreateForm, self).save()
    
        my_field = forms.CharField()
    

    initial 传递给超类并让它完成工作对我来说似乎比直接在字段实例上设置它更干净。

    【讨论】:

    • 我想作为初始值的值来自调用表单的视图,这就是我想将它作为参数传递的原因。而且实际上我不只是想将它用作初始值,而是在保存方法中执行 sql 查询
    【解决方案5】:

    您只需在super() 之前弹出您的arg 并将其放入fields 字典中super() 之后:

    class EpisodeCreateForm(forms.Form):
    
        my_field = forms.CharField(label='My field:')
    
        def __init__(self, *args, **kwargs):
            my_arg = kwargs.pop('my_arg')
            super(EpisodeCreateForm, self).__init__(*args, **kwargs)
            self.fields['my_arg'].initial = my_arg
    

    然后,只需调用

    form = EpisodeCreateForm (my_arg=foo)
    

    例如,假设您有一个剧集表,并且您想在选择菜单中显示可用的剧集,然后选择当前剧集。为此,请使用ModelChoiceField

    class EpisodeCreateForm(forms.Form):
    
        available_episode_list = Episode.objects.filter(available=True)
    
        my_field = forms.ModelChoiceField(label='My field:',
            queryset=available_episode_list)
    
        def __init__(self, *args, **kwargs):
            cur_ep = kwargs.pop('current_episode')
            super(EpisodeCreateForm, self).__init__(*args, **kwargs)
            self.fields['current_episode'].initial = cur_ep
    

    【讨论】:

      猜你喜欢
      • 2020-04-13
      • 2013-01-17
      • 2018-12-11
      • 2011-01-15
      • 2015-07-10
      • 2020-03-21
      • 1970-01-01
      • 2011-11-10
      • 1970-01-01
      相关资源
      最近更新 更多