Django: Access request object from admin's form.clean()

≯℡__Kan透↙ 提交于 2019-12-17 18:38:04

问题


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.


回答1:


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



回答2:


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.




回答3:


There's another possibility: in your view, override get_form_kwargs and add the request:

class FilesUploadCreateView(LoginRequiredMixin, generic.CreateView):
    def get_form_kwargs(self):
        result = super(FilesUploadCreateView, self).get_form_kwargs()
        result['request'] = self.request
        return result

and now in your Form, remember it:

class UploadFilesForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request')
        super(UploadFilesForm, self).__init__(*args, **kwargs)

and now you have access anywhere in your Form with self.request!



来源:https://stackoverflow.com/questions/2683689/django-access-request-object-from-admins-form-clean

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!