Django:如何获取pipe理员表单中的当前用户

在Django的ModelAdmin中,我需要显示根据用户拥有的权限自定义的表单。 有没有办法让当前的用户对象进入窗体类,以便我可以在__init__方法中自定义窗体?
我认为保存当前的请求在本地线程将是一种可能性,但这将是我最后的手段,认为我认为这是一个糟糕的devise方法….

这是我最近做了一个博客:

 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 

我现在可以通过访问self.current_user来访问我的forms.ModelForm的当前用户

编辑:这是一个旧的答案,最近看,我意识到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

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 

有关此方法的更多详细信息,请参阅相关的Django文档

我想我find了一个适用于我的解决scheme:创build一个ModelForm Django使用pipe理的formfield_for_db_field – 方法作为callback。
所以我已经覆盖了这个方法在我的pipe理和传递当前用户对象作为每个字段的属性(这可能不是最有效的,但比使用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__的forms访问当前用户对象:

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

偶然发现了同样的事情,这是第一个谷歌的结果在我的网页上.Dint帮助,一点点googlesearch和工作!

下面是它对我的工作原理(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 

另一种解决这个问题的方法是使用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) 

这个用例在ModelAdmin.get_form中有logging

如果你想为超级用户提供额外的领域,你可以像这样交换一个不同的基础forms:

 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)