Джанго: Как получить текущего пользователя в административных формах - PullRequest
44 голосов
/ 19 мая 2010

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

Ответы [ 6 ]

53 голосов
/ 22 января 2011

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

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)

21 голосов
/ 07 ноября 2014

Ответ Джошмейкера не работает для меня на Джанго 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

5 голосов
/ 19 мая 2010

Мне кажется, я нашел решение, которое работает для меня: для создания 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 голосов
/ 14 июля 2017

Этот вариант использования задокументирован в 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)
3 голосов
/ 09 мая 2017

Еще один способ решить эту проблему - использовать карри 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)

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

class BlogPostForm(forms.ModelForm):

   def __init__(self, *args, **kwargs):
       self.current_user = kwargs.pop('current_user')
       super(BlogPostForm, self).__init__(*args, **kwargs)
2 голосов
/ 19 октября 2016

наткнулся на то же самое, и это был первый результат Google на моей странице. Не помогло, немного погуглил и работал !!

Вот как это работает для меня (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
...