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