web-dev-qa-db-fra.com

Django: Comment obtenir l'utilisateur actuel dans les formulaires d'administration

Dans ModelAdmin de Django, j'ai besoin d'afficher des formulaires personnalisés en fonction des autorisations d'un utilisateur. Existe-t-il un moyen d'obtenir l'objet utilisateur actuel dans la classe de formulaire, afin que je puisse personnaliser le formulaire dans son __init__ méthode?
Je pense que la sauvegarde de la demande actuelle dans un thread local serait une possibilité, mais ce serait mon dernier recours, je pense que c'est une mauvaise approche de conception ....

47
Bernhard Vallant

Voici ce que j'ai fait récemment pour un blog:

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

Je peux maintenant accéder à l'utilisateur actuel dans mon forms.ModelForm en accédant à self.current_user

EDIT: Ceci est une vieille réponse, et en la regardant récemment, j'ai réalisé que le get_form la méthode devrait être modifiée comme suit:

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

(Notez l'ajout de *args)

53
Joshmaker

La réponse de Joshmaker ne fonctionne pas pour moi sur Django 1.7. Voici ce que je devais faire pour 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

Pour plus de détails sur cette méthode, veuillez consulter cette documentation Django

21
sid-kap

Je pense avoir trouvé une solution qui fonctionne pour moi: pour créer un ModelForm Django utilise le formfield_for_db_field- méthode comme rappel.
.

    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

Maintenant, je peux accéder à l'objet utilisateur actuel dans les formulaires __init__ avec quelque chose comme:

    current_user=self.fields['fieldname'].user
5
Bernhard Vallant

Ce cas d'utilisation est documenté à ModelAdmin.get_form

[...] si vous vouliez offrir des champs supplémentaires aux superutilisateurs, vous pouvez échanger sous une forme de base différente comme ceci:

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)

Si vous avez juste besoin d'enregistrer un champ, vous pouvez simplement remplacer 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
ptim

Vous pouvez également résoudre ce problème en utilisant Django currying, ce qui est un peu plus propre que de simplement attacher l'objet de demande au modèle de formulaire.

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)

Cela a l'avantage supplémentaire de rendre votre méthode init sur votre formulaire un peu plus claire car les autres comprendront qu'elle est passée en tant que kwarg et pas seulement en tant qu'attribut attaché au hasard à l'objet classe avant l'initialisation.

class BlogPostForm(forms.ModelForm):

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

tombé sur la même chose et ce fut le premier résultat google sur ma page.

Voici comment cela fonctionne pour moi (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 ['[email protected]']:
            raise ValidationError("Please behave, you are not authorised.....Thank you!!")
        return cleaned_data
2
NoobEditor