2011-10-27 22 views
13

C'è un modo per rendere un modello di sola lettura nell'amministratore di django? ma intendo l'intero modello. Quindi, nessuna aggiunta, nessuna cancellazione, nessuna modifica, basta vedere gli oggetti e i campi, tutto come di sola lettura?Modello intero in sola lettura

+1

Sembra che lavori in corso: https: // github.com/django/django/pull/5297 – Bosco

risposta

11

ModelAdmin fornisce le get_readonly_fields gancio() - Quello che segue è testato, la mia idea è di determinare tutti i campi il modo ModelAdmin lo fa, senza incorrere in una ricorsione con la sola lettura se stessi campi:

from django.contrib.admin.util import flatten_fieldsets 

class ReadOnlyAdmin(ModelAdmin): 
    def get_readonly_fields(self, request, obj=None): 
     if self.declared_fieldsets: 
      fields = flatten_fieldsets(self.declared_fieldsets) 
     else: 
      form = self.get_formset(request, obj).form 
      fields = form.base_fields.keys() 
     return fields 

poi sottoclasse/mixin questo admin dove dovrebbe essere un amministratore di sola lettura.

Per aggiungere/cancellare, e per rendere i loro pulsanti scompaiono, probabilmente anche voler aggiungere

def has_add_permission(self, request): 
     # Nobody is allowed to add 
     return False 
    def has_delete_permission(self, request, obj=None): 
     # Nobody is allowed to delete 
     return False 

PS: In ModelAdmin, se has_change_permission (ricerca o il vostro override) restituisce false, si don' t ottenere la vista di modifica di un oggetto - e il collegamento ad esso non verrà nemmeno mostrato. Sarebbe davvero bello se lo facesse, e il default get_readonly_fields() controllò il permesso di modifica e impostò tutti i campi in sola lettura in quel caso, come sopra. In questo modo i non-changer potrebbero almeno sfogliare i dati ... dato che la struttura amministrativa attuale assume view = edit, come sottolinea il jathanism, questo probabilmente richiederebbe l'introduzione di un'autorizzazione "view" oltre a add/change/delete ...

EDIT: per quanto riguarda l'impostazione di tutti i campi di sola lettura, anche non testato ma guardando promettente:

readonly_fields = MyModel._meta.get_all_field_names() 

EDIT: Ecco un altro uno

if self.declared_fieldsets: 
    return flatten_fieldsets(self.declared_fieldsets) 
else: 
    return list(set(
     [field.name for field in self.opts.local_fields] + 
     [field.name for field in self.opts.local_many_to_many] 
    )) 
+1

P.S .: ora ho creato una richiesta di funzionalità in questo senso https://code.djangoproject.com/ticket/17295 –

+1

Nota: il metodo get_formset è definito solo per InlineModelAdmin –

+0

Ciao, grazie per questa raccolta di opzioni. Potrebbe essere educato anche a fornire i link alle risposte da cui hai preso i pezzi, perché vedo che non sono tutti tuoi. Un altro aspetto positivo sarebbe che i lettori potrebbero anche vedere i commenti fatti da altri su ciascuno dei suggerimenti. – steps

2

È possibile personalizzare le classi ModelAdmin con l'attributo readonly_fields. Vedi this answer per ulteriori informazioni.

+0

ma c'è un modo per rendere il ** modello ** come read_only, senza dover aggiungere tutti i suoi attributi alla lista readonly_fields? – juliomalegria

+1

C'è, ma non facilmente. Sei in grado di creare permessi personalizzati in Django, ma quando si tratta del sito di amministrazione non è banale. Django presuppone che, se le persone sono autorizzate a visualizzare il contenuto nell'interfaccia di amministrazione, possono anche modificarlo. Puoi provare il suggerimento da [questa domanda] (http://stackoverflow.com/questions/4334049/make-a-django-model-read-only) se ti senti audace. IMO è solo più facile impostare in modo esplicito tutti i campi in lettura e andare avanti. – jathanism

0

ho avuto uno scenario simile in cui:

  1. L'utente dovrebbe essere in grado di creare il modello oggetti
  2. L'utente dovrebbe essere in grado di visualizzare elenco di modello di oggetti
  3. utente should'nt essere in grado di modificare un oggetto una volta che è stato creato

1 Sovrascrittura della vista Cambia

Poiché è possibile sovrascrivere lo change_view() in un ModelAdmin, è possibile sfruttarlo per impedire la modifica delle istanze del modello una volta che sono state create. Ecco un esempio che ho usato:

def change_view(self, request, object_id, form_url='', extra_context=None): 
    messages.error(request, 'Sorry, but editing is NOT ALLOWED') 
    return redirect(request.META['HTTP_REFERER']) 

2.Condizionatamente Modifica Modifica autorizzazioni

Ho anche capito che la documentazione interpretano il risultato di ModelAdmin.has_change_permission() in diversi modi:

Should return True if editing obj is permitted, False otherwise. If obj is None, should return True or False to indicate whether editing of objects of this type is permitted in general (e.g., False will be interpreted as meaning that the current user is not permitted to edit any object of this type).

Significato ho potuto controllare se obj è None, nel qual caso torno True, altrimenti torno False , e questo in effetti consente agli utenti di visualizzare l'elenco delle modifiche, ma non essere in grado di modificare né visualizzare il change_form dopo aver salvato l'istanza del modello.

def has_change_permission(self, request, obj = None, **kwargs): 
    if obj is None: 
     return True 
    else: 
     return False 

Anche se penso che questo potrebbe anche ignorare qualsiasi MODEL_can_change permessi permettendo occhi indiscreti di visualizzare il cambiamento-list?

-1

Secondo la mia prova su Django 1.8 che non è possibile utilizzare in seguito come notato in risposta # 3, ma funziona su Django 1.4:

##  self.get_formset(request, obj)  ## 
answer 3 needs fix. Generally, alternative codes for this issue about below section 
##   form = self.get_formset(request, obj).form ## 
##   fields = form.base_fields.keys()    ## 

Può essere qualcosa di simile:

#~ (A) or 
[f.name for f in self.model._meta.fields] 

#~ (B) or 
MyModel._meta.get_all_field_names() 

#~ (C) 
list(set([field.name for field in self.opts.local_fields] + 
         [field.name for field in self.opts.local_many_to_many]   
)) 
3

come "vista autorizzazioni "will not make it into Django 1.11, sfortunatamente, ecco una soluzione che rende il tuo ModelAdmin di sola lettura entro il facendo sia il salvataggio delle modifiche del modello che l'aggiunta delle voci del registro cronologico del modello un no-op.

def false(*args, **kwargs): 
    """A simple no-op function to make our changes below readable.""" 
    return False 

class MyModelReadOnlyAdmin(admin.ModelAdmin): 
    list_display = [ 
     # list your admin listview entries here (as usual) 
    ] 
    readonly_fields = [ 
     # list your read-only fields here (as usual) 
    ] 

    actions = None 
    has_add_permission = false 
    has_delete_permission = false 
    log_change = false 
    message_user = false 
    save_model = false 

(NOTA:. non confondere l'aiutante false no-op con il False incorporato Se non simpatizzare con la funzione di supporto al di fuori della classe di spostarlo nella classe, lo chiamano no_op o qualcosa di diverso, o ignorare gli attributi affetti da usuali def s meno secca, ma se non vi interessa ...)

Questo sarà:.

  1. rimuovere le azioni casella a discesa (Con "delete") nella lista
  2. respingere l'aggiunta di nuovo modello voci
  3. respingere modello eliminando voci esistenti
  4. evitare di creare voci di registro nella storia del modello
  5. evitare la visualizzazione "è stato cambiato con successo" i messaggi dopo il salvataggio
  6. evitare di salvare le modifiche al database changeform

non sarà:

  • rimuovere o sostituire i due pulsanti "Salva e continuare l'editing" e "SAVE" (che sarebbe bello per migliorare l'esperienza degli utenti)

noti che get_all_field_names (come indicato nella risposta accettata) era removed in Django 1.10. Testato con Django 1.10.5.