Django:来自admin的form.clean()的访问请求对象

时间:2010-04-21 14:16:52

标签: django django-admin django-forms

我的问题与此问题非常相似:How do I access the request object or any other variable in a form's clean() method?

除此之外,管理员表格存在同样的问题。所以我无法看到自己初始化表单的方法,因此 - 将请求传递给它。

事先谢谢。

4 个答案:

答案 0 :(得分:39)

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

您需要ModelAdmin.get_form()提供subclass 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

答案 1 :(得分:0)

ModelAdmin类中有许多钩子允许你这样做 - 查看django.contrib.admin.options中的代码。

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

在评论后编辑

你是完全正确的,这不会让你根据用户的权限验证表单。不幸的是,表单实例化深埋在add_view的{​​{1}}和change_view方法中。

没有很多可能性而没有复制很多现有代码。您可以覆盖ModelAdmin方法;或者你可以尝试覆盖*_view函数来返回一个新的类,其中已经发出请求对象;或者你可以尝试摆弄表单类modelform_factory方法来做同样的事情,但由于元类的形式,这很棘手。

答案 2 :(得分:0)

还有另一种可能性:您认为覆盖get_form_kwargs并添加request

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

现在在您的表单中,记住它:

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

现在,您可以使用self.request访问表单中的任何位置!

答案 3 :(得分:0)

此解决方案对我有用。您可以在表单的任何位置使用def decode(string_for_decoding: str): result = "" for i in range(0, len(string_for_decoding)): if len(string_for_decoding) > i + 1 and string_for_decoding[i + 1].isdigit(): result += string_for_decoding[i] * int(string_for_decoding[i + 1]) elif string_for_decoding.isalpha(): result += string_for_decoding[i] return result print(decode(input("Enter a string to decode: "))) ,包括self.request

def clean(self)