Django: объект запроса доступа от admin form.clean()

Мой вопрос очень похож на этот: Как получить доступ к объекту запроса или любой другой переменной в методе clean() формы?

Кроме того, у меня такая же проблема с формой администратора. Поэтому я не вижу способа самостоятельно инициировать форму, поэтому - передать ей запрос.

Спасибо заранее.

Ответ 1

Действительно, есть способ решить вашу проблему!

Вам нужно подклассу, предоставленную ModelAdmin.get_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

Ответ 2

В классе ModelAdmin есть несколько крючков, чтобы вы могли это сделать - посмотрите код в django.contrib.admin.options.

Два метода, которые могут вам помочь, это ModelAdmin.save_form и ModelAdmin.save_model, оба из которых передаются объекту запроса. Таким образом, вы можете переопределить эти методы в подклассе Admin и выполнить любую дополнительную обработку.

Отредактировано после комментария

Вы совершенно правы, что это не позволит вам проверить форму, зависящую от пользовательских привилегий. К сожалению, экземпляр формы хранится глубоко внутри методов add_view и change_view ModelAdmin.

Существует не так много возможностей, не дублируя много существующего кода. Вы можете переопределить методы *_view; или вы можете попробовать и переопределить функцию modelform_factory, чтобы вернуть новый класс с уже запрограммированным объектом запроса; или вы можете попробовать fiddling с помощью метода класса __new__ сделать то же самое, но это сложно из-за метакласса формы.