如何将额外的参数传递给 django admin 自定义表单?

Posted

技术标签:

【中文标题】如何将额外的参数传递给 django admin 自定义表单?【英文标题】:How to pass an extra argument to django admin custom form? 【发布时间】:2016-12-13 04:35:06 【问题描述】:

如您所知,我们可以定义一个 ModelForm,然后通过在 modelAdmin 类中设置 form 属性来替换添加和更改表单。例如:

class FooAdminForm(django.forms.ModelForm):
     class Meta:
         model = Foo

     def __init__(self, *args, **kwargs):
         super(FooAdminForm, self).__init__(self, *args, **kwargs)


class FooAdmin(admin.ModelAdmin):
    form = FooAdminForm

在一个简单的视图中,我们可以初始化一个表单对象并将额外的参数传递给表单的 init 函数。像这样:

def my_view(request):
    form = FooAdminForm(p1='aaa', p2='bbb')

然后在init函数中我们可以访问这些参数。

self.p1 = kwargs.pop('p1')
self.p2 = kwargs.pop('p2')

但是如何将参数传递给 modelAdmin 表单?我只能将表单类传递给modelAdmin表单属性,不能像在视图中那样初始化它。

我在这里找到了关于 *** 的解决方案:

Use a form with a custom __init__ in Django Admin

但它为表单对象添加了一个动态属性,我认为这有点骇人听闻。有没有更好或更正式的方式来做到这一点?

【问题讨论】:

你有没有找到更好的方法? 使用functools.partial 比设置类属性要好,但仍然很麻烦:( @djvg 这个答案也解决了这个问题并且有很多赞成票。 ***.com/questions/2683689/… but it adds a dynamic attribute to form object — 这是正确的做法。 【参考方案1】:

我一直在寻找解决方案,并在 Django 的问题跟踪器中找到了一个相当优雅的解决方案:

def get_form(self, request, obj=None, **kwargs):
    Form = super().get_form(request, obj=None, **kwargs)
    return functools.partial(Form, user=request.user)

https://code.djangoproject.com/ticket/27240#comment:9

因此,如果您使用的是自定义表单,您只需使用 kwargs 将其传递给 super().get_form()

def get_form(self, request, obj=None, **kwargs):
    kwargs['form'] = FooAdminForm
    Form = super().get_form(request, obj=None, **kwargs)
    return functools.partial(Form, user=request.user)

【讨论】:

【参考方案2】:

因为ModelAdmin.get_form 的行为与FormView.get_form 不太一样,所以你需要有点偷偷摸摸:

https://docs.djangoproject.com/en/3.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_form

class FooAdmin(admin.ModelAdmin):
    form = FooAdminForm

    def get_form(self, request, obj=None, **kwargs):
        form_class = super().get_form(request, obj, **kwargs)
        class Form(form_class):
            def __init__(self, *args, **kwargs):
                kwargs.update(foo='bar')
                super().__init__(self, *args, **kwargs)
        return Form

【讨论】:

错误是modelform_factory() got an unexpected keyword argument 'foo',因为get_form 初始化了modelform_factory 并提供了ModelForm class,而不是实例。 docs 啊,我的错。 ModelAdmin.get_form 的行为与 View.get_form 不同... 您也许可以使用functools.partial 将关键字参数添加到super().get_form(...) 的结果中,但这有点笨拙... 不适合我,我得到 AttributeError: Form' object has no attribute 'get'。在 Django 2.2 上,但我不认为这有什么不同。 gabn88: 你确定你输入正确吗?我的回答中没有.get() 电话,只有.get_form

以上是关于如何将额外的参数传递给 django admin 自定义表单?的主要内容,如果未能解决你的问题,请参考以下文章

如何将额外的额外参数传递给批处理文件?

如何使用 withColumn 将额外的参数传递给 UDF

如何将额外的参数传递给 Vision 框架?

将额外参数传递给事件处理程序?

将额外的参数传递给IntersectionObserver?

将额外参数传递给 usort 回调