2010-05-19 13 views
43

In Django's ModelAdmin ho bisogno di visualizzare i moduli personalizzati in base alle autorizzazioni che un utente ha. C'è un modo per ottenere l'oggetto utente corrente nella classe form, in modo che io possa personalizzare il modulo nel suo metodo __init__?
Penso che salvare la richiesta corrente in un thread locale sarebbe una possibilità ma questa sarebbe la mia ultima risorsa. Penso che sia un cattivo approccio al design ....Django: Come ottenere l'utente corrente nei moduli di amministrazione

risposta

49

Ecco quello che ho fatto di recente per 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 

posso ora accedere l'utente corrente nel mio forms.ModelForm accedendo self.current_user

EDIT: Questa è una risposta vecchia, e guardando di recente ho capito il metodo get_form dovrebbe essere modificato per essere:

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

(notare l'aggiunta di *args)

5

Penso di aver trovato una soluzione che funzioni per me: per creare un ModelForm Django usa il metodo di amministrazione formfield_for_db_field come un callback.
Così ho sovrascritto questo metodo nella mia amministrazione e passare l'oggetto utente corrente come un attributo con tutti i campi (che non è probabilmente il più efficiente, ma sembra più pulito per me che utilizzano 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 

ora posso accedere all'oggetto utente corrente nelle forme __init__ con qualcosa di simile:

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

questa è una 'AttributeError':' kwargs.get ('richiesta', None) .user' – hcalves

20

La risposta di Joshmaker non funziona per me su Django 1.7. Ecco quello che ho dovuto fare per 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 

Per maggiori dettagli su questo metodo, vedere this relevant Django documentation

+0

genio, sono rimasto bloccato in questo problema vero duro – bobleujr

2

capitati stessa cosa e questo è stato il primo risultato di Google sul mio page.Dint aiutato, po più googling e lavorato !!

Ecco come funziona per me (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

bella piccola soluzione, :) –

+0

grazie amico! :) – NoobEditor

1

Un altro modo è possibile risolvere questo problema è quello di utilizzare Django accattivarsi, che è un po 'più pulito di un semplice allegando l'oggetto di richiesta al modulo modello.

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) 

Questo ha il vantaggio rendendo il vostro metodo di init sul modulo un po 'più chiaro come gli altri capiranno che è in fase di passato come kwarg e non solo attaccato in modo casuale attributo all'oggetto classe prima dell'inizializzazione.

class BlogPostForm(forms.ModelForm): 

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

Questo caso d'uso è documentato in ModelAdmin.get_form

[...] Se si voleva offrire ulteriori campi di superuser, si potrebbe scambiare in una forma base diversa in questo modo:

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) 

Se avete solo bisogno di salvare un campo, allora si può solo ignorare 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) 
Problemi correlati