Django:如何在管理表单中获取当前用户

时间:2010-05-19 11:17:25

标签: django django-forms django-admin username

在Django的ModelAdmin中,我需要显示根据用户拥有的权限定制的表单。有没有办法将当前用户对象添加到表单类中,以便我可以使用__init__方法自定义表单?
我认为在本地线程中保存当前请求是可能的,但这是我的最后手段,我认为我认为这是一种糟糕的设计方法....

6 个答案:

答案 0 :(得分:52)

以下是我最近为博客所做的事情:

class BlogPostAdmin(admin.ModelAdmin):
    form = BlogPostForm

    def get_form(self, request, **kwargs):
         form = super(BlogPostAdmin, self).get_form(request, **kwargs)
         form.current_user = request.user
         return form

我现在可以通过访问forms.ModelForm

来访问self.current_user中的当前用户

编辑:这是一个陈旧的答案,最近看到它我意识到get_form方法应该修改为:

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

(注意添加*args

答案 1 :(得分:21)

Joshmaker的回答对Django 1.7不起作用。这是我为Django 1.7做的事情:

class BlogPostAdmin(admin.ModelAdmin):
    form = BlogPostForm

    def get_form(self, request, obj=None, **kwargs):
        form = super(BlogPostAdmin, self).get_form(request, obj, **kwargs)
        form.current_user = request.user
        return form

有关此方法的详细信息,请参阅this relevant Django documentation

答案 2 :(得分:5)

我认为我找到了一个适合我的解决方案:创建ModelForm Django使用管理员的formfield_for_db_field - 方法作为回调。
所以我在管理员中覆盖了这个方法,并将当前用户对象作为每个字段的属性传递(这可能不是最有效但对我来说比使用threadlocals更清晰:

    def formfield_for_dbfield(self, db_field, **kwargs):
        field = super(MyAdmin, self).formfield_for_dbfield(db_field, **kwargs)
        field.user = kwargs.get('request', None).user
        return field

现在,我可以使用以下内容访问表单__init__中的当前用户对象:

    current_user=self.fields['fieldname'].user

答案 3 :(得分:3)

此用例记录在ModelAdmin.get_form

  

[...]如果你想为超级用户提供额外的字段,你可以换成不同的基本形式,如下所示:

class MyModelAdmin(admin.ModelAdmin):
    def get_form(self, request, obj=None, **kwargs):
        if request.user.is_superuser:
            kwargs['form'] = MySuperuserForm
        return super().get_form(request, obj, **kwargs)

如果您只需要保存字段,则可以覆盖ModelAdmin.save_model

from django.contrib import admin

class ArticleAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        obj.user = request.user
        super().save_model(request, obj, form, change)

答案 4 :(得分:2)

偶然发现了同样的事情,这是我页面上的第一个谷歌搜索结果.Dint帮助,更多谷歌搜索和工作!!

以下是它对我有用的方法(django 1.7+):

class SomeAdmin(admin.ModelAdmin):
    # This is important to have because this provides the
    # "request" object to "clean" method
    def get_form(self, request, obj=None, **kwargs):
        form = super(SomeAdmin, self).get_form(request, obj=obj, **kwargs)
        form.request = request
        return form

class SomeAdminForm(forms.ModelForm):
    class Meta(object):
        model = SomeModel
        fields = ["A", "B"]

    def clean(self):
        cleaned_data = super(SomeAdminForm, self).clean()
        logged_in_email = self.request.user.email #voila
        if logged_in_email in ['abc@abc.com']:
            raise ValidationError("Please behave, you are not authorised.....Thank you!!")
        return cleaned_data

答案 5 :(得分:2)

另一种解决此问题的方法是使用Django currying,它比将请求对象附加到表单模型要简单得多。

from django.utils.functional import curry

class BlogPostAdmin(admin.ModelAdmin):
    form = BlogPostForm

    def get_form(self, request, **kwargs):
        form = super(BlogPostAdmin, self).get_form(request, **kwargs)
        return curry(form, current_user=request.user)

这有一个额外的好处,使你的表单上的 init 方法更加清晰,因为其他人会理解它在初始化之前作为kwarg而不是随机附加属性传递给类对象。

class BlogPostForm(forms.ModelForm):

   def __init__(self, *args, **kwargs):
       self.current_user = kwargs.pop('current_user')
       super(BlogPostForm, self).__init__(*args, **kwargs)