Django:从管理员的 form.clean() 访问请求对象

发布于 2024-08-29 12:40:17 字数 263 浏览 5 评论 0原文

我的问题与此非常相似: 如何访问请求对象或表单的 clean() 方法中的任何其他变量?

除此之外,我对管理表单也有同样的问题。因此,我看不到自己初始化表单的方法,因此 - 将请求传递给它。

预先感谢。

My question is very similar to this one: How do I access the request object or any other variable in a form's clean() method?

Except, I have the same problem with admin form. So I can't see a way to init the form myself, therefore - to pass a request to it.

Thanks beforehand.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

絕版丫頭 2024-09-05 12:40:17

确实,有一种方法可以解决您的问题!

您将需要子类化由 ModelAdmin.get_form() 提供的 form 并覆盖它:

class BusinessDocumentCommentForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request', None)
        # Voila, now you can access request anywhere in your form methods by using self.request!
        super(BusinessDocumentCommentForm, self).__init__(*args, **kwargs)
        if self.request.GET.get('document_pk', False):
            #Do something
    def clean(self):
        # Do something with self.request
        # etc.    
    class Meta:
        model = BusinessDocumentComment

class BusinessDocumentCommentAdmin(admin.ModelAdmin):

    form = BusinessDocumentCommentForm     

    def get_form(self, request, obj=None, **kwargs):

        AdminForm = super(BusinessDocumentCommentAdmin, self).get_form(request, obj, **kwargs)

        class AdminFormWithRequest(AdminForm):
            def __new__(cls, *args, **kwargs):
                kwargs['request'] = request
                return AdminForm(*args, **kwargs)

        return AdminFormWithRequest

Indeed, there is a way to solve your issue!

You will need to subclass form provided by ModelAdmin.get_form() and override it:

class BusinessDocumentCommentForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request', None)
        # Voila, now you can access request anywhere in your form methods by using self.request!
        super(BusinessDocumentCommentForm, self).__init__(*args, **kwargs)
        if self.request.GET.get('document_pk', False):
            #Do something
    def clean(self):
        # Do something with self.request
        # etc.    
    class Meta:
        model = BusinessDocumentComment

class BusinessDocumentCommentAdmin(admin.ModelAdmin):

    form = BusinessDocumentCommentForm     

    def get_form(self, request, obj=None, **kwargs):

        AdminForm = super(BusinessDocumentCommentAdmin, self).get_form(request, obj, **kwargs)

        class AdminFormWithRequest(AdminForm):
            def __new__(cls, *args, **kwargs):
                kwargs['request'] = request
                return AdminForm(*args, **kwargs)

        return AdminFormWithRequest
月依秋水 2024-09-05 12:40:17

这个解决方案对我有用。您可以在表单中的任何位置使用 self.request 来使用它,包括 def clean(self)

class MyModelAdmin(admin.ModelAdmin):
    form = MyForm

    def get_form(self, request, *args, **kwargs):
        form = super(MyModelAdmin, self).get_form(request, *args, **kwargs)
        form.request = request
        return form

This solution works for me. You can use self.request anywhere in the form to use it, including def clean(self)

class MyModelAdmin(admin.ModelAdmin):
    form = MyForm

    def get_form(self, request, *args, **kwargs):
        form = super(MyModelAdmin, self).get_form(request, *args, **kwargs)
        form.request = request
        return form
暖心男生 2024-09-05 12:40:17

ModelAdmin 类中有许多挂钩可以让您执行此操作 - 请查看 django.contrib.admin.options 中的代码。

ModelAdmin.save_formModelAdmin.save_model 这两个方法可能对您有帮助,这两个方法都传递请求对象。因此,您可以在 Admin 子类中重写这些方法并执行您需要的任何额外处理。

评论后编辑

您说得很对,这不会让您根据用户的权限验证表单。不幸的是,表单实例化深深地埋藏在 ModelAdminadd_viewchange_view 方法中。

如果不复制大量现有代码,就没有太多可能性。您可以重写 *_view 方法;或者您可以尝试重写 modelform_factory 函数以返回一个已嵌入请求对象的新类;或者您可以尝试摆弄表单类 __new__ 方法来执行相同的操作,但由于表单元类,这很棘手。

There are a number of hooks in the ModelAdmin class to allow you to do things this - look at the code in django.contrib.admin.options.

Two methods that might help you are ModelAdmin.save_form and ModelAdmin.save_model, both of which are passed the request object. So you can override these methods in your Admin subclass and do any extra processing you need.

Edited after comment

You're quite right that this won't let you validate the form dependent on the user's privileges. Unfortunately the form instantiation is buried deep within the add_view and change_view methods of ModelAdmin.

There aren't many possibilities without duplicating a lot of existing code. You could override the *_view methods; or you could try and override the modelform_factory function to return a new class with the request object baked in already; or you could try fiddling with the form class __new__ method to do the same thing, but that's tricky because of the form metaclass.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文