2010-05-19 35 views
43

En ModelAdmin de Django, necesito mostrar formularios personalizados según los permisos que tiene un usuario. ¿Hay alguna manera de obtener el objeto de usuario actual en la clase de formulario, para poder 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 ....Django: Cómo obtener el usuario actual en formularios de administrador

Respuesta

49

Aquí 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 puede acceder el usuario actual en mi forms.ModelForm accediendo self.current_user

EDIT: Esta es una respuesta de edad, y mirándolo Hace poco se dio cuenta el método get_form debe modificarse para ser:

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

(Observe la adición de *args)

5

Creo que encontré una solución que funciona para mí: Para crear un ModelForm Django usa el método formfield_for_db_field del administrador como una devolución de llamada.
Así que han sobrescrito este método en mi administrador y pasar el objeto de usuario actual como un atributo con cada campo (que probablemente no es el más eficiente, pero parece más limpio para mí que utilizan 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 usuario actual en las formas __init__ con algo como:

current_user=self.fields['fieldname'].user 
+2

se trata de un 'AttributeError':' kwargs.get ('solicitud', Ninguna) .user' – hcalves

20

La respuesta de Joshmaker no funciona para mí en Django 1.7. Aquí es lo que tenía 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 más detalles sobre este método, por favor ver this relevant Django documentation

+0

genio, me he quedado atrapado en este problema muy duro – bobleujr

2

topamos con lo mismo y este fue el primer resultado de Google en mi page.Dint ayudó, poco más Google y funcionó !!

Aquí es cómo 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 
+1

poco agradable solución, gracias :) –

+0

amigo! :) – NoobEditor

1

Otra manera de resolver este problema es mediante el uso de Django currificación que es un poco más limpio que acaba de fijar el objeto de la petición a la forma modelo.

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 su init método en su forma un poco más claro como otros entenderá que está siendo pasado como kwarg y no sólo une al azar atributo a la clase de objeto 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) 
0

Este caso de uso está documentado en ModelAdmin.get_form

[...] Si desea ofrecer campos adicionales a los superusuarios, usted podría intercambiar en 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 sólo tiene que guardar un campo, entonces usted 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) 
Cuestiones relacionadas