2010-05-19 3 views
43

В модели Django ModelAdmin мне нужно отображать формы, настроенные в соответствии с разрешениями пользователя. Есть ли способ получить текущий объект пользователя в класс формы, чтобы я мог настроить форму в своем методе __init__?
Я думаю, что сохранение текущего запроса в потоке локально было бы возможно, но это было бы моим последним средством, я думаю, что это плохой подход к дизайну.Django: Как получить текущего пользователя в админ-формах

ответ

49

Вот что я сделал недавно для блога:

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

EDIT: Это старый ответ, и, глядя на него в последнее время я понял, что метод 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)

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 
+2

Это 'AttributeError':' kwargs.get ('запрос', None) .user' – hcalves

20

Ответ 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

+0

гений, я застрял в этой задаче очень трудно – bobleujr

2

наткнулся на одно и то же, и это был первый результат Google на мой page.Dint помог, немного больше googling и работал !!

Вот как это работает для меня (Джанго 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 ['[email protected]']: 
      raise ValidationError("Please behave, you are not authorised.....Thank you!!") 
     return cleaned_data 
+1

миленькая обходной, :) –

+0

спасибо дружище! :) – NoobEditor

1

Другим способом вы можете решить эту проблему заключается в использовании Django каррирование который немного чище, чем просто прикрепление объект запроса к форме модель.

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) 

Это имеет дополнительное преимущество, что делает ваш инициализации метода на форме немного более ясно, как другие поймут, что это передается как kwarg, а не просто случайным образом прикреплен атрибут объекта класса до инициализации.

class BlogPostForm(forms.ModelForm): 

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

Этот случай использования документирована в 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) 
Смежные вопросы