【问题标题】:adding new form fields dynamically in admin在管理员中动态添加新表单字段
【发布时间】:2011-04-19 15:27:09
【问题描述】:

我正在尝试为管理界面中使用的表单动态添加新表单字段(我使用了这个blog post):

class ServiceRoleAssignmentForm(forms.ModelForm):

    class Meta:
        model = ServiceRoleAssignment

    def __init__(self, *args, **kwargs):
        super(ServiceRoleAssignmentForm, self).__init__(*args, **kwargs)
        self.fields['test'] = forms.CharField(label='test') 


class ServiceRoleAssignmentAdmin(admin.ModelAdmin):
    form = ServiceRoleAssignmentForm

admin.site.register(ServiceRoleAssignment, ServiceRoleAssignmentAdmin)

但是,无论我尝试什么,该字段都不会出现在我的管理表单上!这可能是与管理员工作方式有关的问题吗?还是 ModelForm ?

感谢您的帮助!

塞巴斯蒂安

PS:我使用的是 django 1.3

【问题讨论】:

    标签: django django-forms


    【解决方案1】:

    在模板中呈现表单时,从字段集变量枚举的字段,而不是从字段。当然,您可以在 AdminForm 中重新定义字段集,但是由于原始表单类没有此类字段,因此验证将失败。我可以提出的一种解决方法是在表单定义中静态定义该字段,然后在表单的 init 方法中动态重新定义该字段。这是一个例子:

    class ServiceRoleAssignmentForm(forms.ModelForm):
        test = forms.Field()
    
        class Meta:
            model = ServiceRoleAssignment
    
        def __init__(self, *args, **kwargs):
            super(ServiceRoleAssignmentForm, self).__init__(*args, **kwargs)
            # Here we will redefine our test field.
            self.fields['test'] = forms.CharField(label='test2')
    

    【讨论】:

    • 感谢您的回答!我实际上正在考虑这样做......但我没有得到这部分“从字段集变量枚举的字段,而不是从字段。当然你可以在你的 AdminForm 中重新定义字段集”。那个字段集变量是什么?您的意思是有一个包含所有字段的“字段”变量,以及一个用于渲染它们的“字段集”?在那种情况下,为什么不将新字段添加到“字段集”和“字段”中???
    • 看看模板。您可能想要覆盖模板(如果您已经覆盖它,则更新它)。
    【解决方案2】:

    实际上,我目前正在解决同样的问题。 虽然不理想,但我找到了一种适用于我的用例的临时解决方法。可能对你有用吗?

    在我的例子中,我有一个静态的字段名称,所以我只是在我的 ModelForm 中声明了它。像往常一样,然后我像往常一样覆盖 init() 以覆盖一些选项。

    即:

    def statemachine_form(for_model=None):
        """
        Factory function to create a special case form
        """
        class _StateMachineBaseModelForm(forms.ModelForm):
            _sm_action = forms.ChoiceField(choices=[], label="Take Action")
    
            class Meta:
                model = for_model
    
            def __init__(self, *args, **kwargs):
                super(_StateMachineBaseModelForm, self).__init__(*args, **kwargs)
                actions = (('', '-----------'),)
                for action in self.instance.sm_state_actions():
                    actions += ((action, action),)
                self.fields['_sm_action'] = forms.ChoiceField(choices=actions,
                                                              label="Take Action")
        if for_model: return _StateMachineBaseModelForm
    
    class ContentItemAdmin(admin.ModelAdmin):
        form = statemachine_form(for_model=ContentItem)
    

    现在,正如我之前提到的,这并不完全是“动态的”,但这暂时适合我。

    我有完全相同的问题,如果我动态添加字段,而不先声明它,那么它实际上并不存在。我认为这实际上与 ModelForm 创建字段的方式有关。

    我希望其他人可以给我们更多信息。

    【讨论】:

    • 哦,您可能会注意到我正在使用工厂函数来生成表单。这是我试图找到解决方案的一部分。我在这里遇到过文档:b-list.org/weblog/2008/nov/09/dynamic-forms
    • 嗯......这确实可行!例如,我可以用隐藏的输入声明 10 个无用的字段,然后动态地“打开它们”……但这不是很漂亮。感谢这个解决方法!目前,我将继续静态声明字段...
    【解决方案3】:
    【解决方案4】:

    在调用super.init之前尝试添加字段:

    def __init__(self, *args, **kwargs):
        self.fields['test'] = forms.CharField(label='test') 
        super(ServiceRoleAssignmentForm, self).__init__(*args, **kwargs)
    

    【讨论】:

    • 在表单上调用 super 之前,fields 属性不存在。
    猜你喜欢
    • 2016-12-18
    • 2015-02-06
    • 2014-08-05
    • 2019-02-03
    • 1970-01-01
    • 2011-11-27
    • 1970-01-01
    • 1970-01-01
    • 2017-07-11
    相关资源
    最近更新 更多