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 ....
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
)
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
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
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)
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)
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