theme - Django: Cómo obtener el usuario actual en formularios de administrador
django-admin command (6)
Creo que encontré una solución que me funciona: para crear un ModelForm
Django usa el formfield_for_db_field
- formfield_for_db_field
del administrador como una devolución de llamada.
Así que he sobrescrito este método en mi administrador y paso el objeto de usuario actual como un atributo con cada campo (que probablemente no sea el más eficiente, pero me parece más limpio que utilizar 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
Ahora puedo acceder al objeto de usuario actual en los formularios __init__
con algo como:
current_user=self.fields[''fieldname''].user
En ModelAdmin de Django, necesito mostrar formularios personalizados de acuerdo con los permisos que tiene un usuario. ¿Hay alguna manera de obtener el objeto de usuario actual en la clase de formulario, de modo que pueda personalizar el formulario en su método __init__
?
Creo que guardar la solicitud actual en un hilo local sería una posibilidad, pero este sería mi último recurso, creo que estoy pensando que es un mal enfoque de diseño ....
Este caso de uso está documentado en ModelAdmin.get_form
[...] si quisiera ofrecer campos adicionales a los superusuarios, podría cambiar una forma de base diferente así:
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 solo necesita guardar un campo, entonces podría anular 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)
Esto es lo que hice recientemente para 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
Ahora puedo acceder al usuario actual en mis forms.ModelForm
accediendo a self.current_user
EDITAR: Esta es una respuesta antigua, y al mirarla recientemente, me di cuenta de que el método get_form
debe enmendarse para que sea:
def get_form(self, request, *args, **kwargs):
form = super(BlogPostAdmin, self).get_form(request, *args, **kwargs)
form.current_user = request.user
return form
(Tenga en cuenta la adición de *args
)
La respuesta de Joshmaker no funciona para mí en Django 1.7. Esto es lo que tuve que hacer para 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
Para obtener más detalles sobre este método, consulte esta documentación relevante de Django
Otra forma de resolver este problema es mediante el uso del currículo de Django, que es un poco más limpio que simplemente asociar el objeto de solicitud al modelo de formulario.
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)
Esto tiene el beneficio adicional de hacer que su método init en su formulario sea un poco más claro, ya que otros comprenderán que se pasa como un kwarg y no solo como un atributo adjunto al objeto de clase antes de la inicialización.
class BlogPostForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.current_user = kwargs.pop(''current_user'')
super(BlogPostForm, self).__init__(*args, **kwargs)
tropecé con lo mismo y este fue el primer resultado de google en mi página. ¡Ayudó, buscó más Google y funcionó!
Así es como funciona para mí (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