Amministratore Django, nascondi un modello


87

Nella pagina principale del sito di amministrazione in cui vengono visualizzati i modelli registrati, desidero nascondere diversi modelli registrati all'amministratore di Django.

Se li annullo direttamente, non sono in grado di aggiungere nuovi record poiché il simbolo di aggiunta nuovo "+" scompare.

Come si può fare ?

Risposte:


124

Sulla base della risposta di x0nix ho fatto alcuni esperimenti. Sembra che la restituzione di un dict vuoto da get_model_permsesclude il modello da index.html, consentendo comunque di modificare direttamente le istanze.

class MyModelAdmin(admin.ModelAdmin):
    def get_model_perms(self, request):
        """
        Return empty perms dict thus hiding the model from admin index.
        """
        return {}

admin.site.register(MyModel, MyModelAdmin)

Concordato. Solo questo è un problema quando non voglio cambiare il codice. Quello che voglio dire è che ho un'app di base che voglio mantenere pulita dalle dipendenze da altre app. Conservo queste dipendenze in un'app derivata specifica del progetto. Ora voglio che l'interfaccia di amministrazione mostri solo l'app derivata, non l'app di base. Django richiede che l'app di base sia elencata in settings / INSTALLED_APPS affinché l'app derivata funzioni. Ovviamente, l'app di base non dovrebbe essere mostrata, ma allo stesso tempo non voglio mantenerla non modificata e riutilizzabile. Vedi [qui] ( Stack Exchange / questions / 13923968 /).
Sven

6
Un modo più breve:get_model_perms = lambda self, req: {}
Tigran Saluev

3
E se volessi nascondere un modello da un determinato userAdmin?
Alireza Sanaee

1
Fai attenzione a questa soluzione: anche se il collegamento scompare, l'utente può saltare all'oggetto stesso in questo modo: / admin / main / comment / 2333 / change /
goodgrief

35

Per Django 1.8 e versioni successive

A partire da Django 1.8, ModelAdminè stato chiamato un nuovo metodo has_module_permission()che è responsabile della visualizzazione di un modello nell'indice di amministrazione.

Per nascondere un modello dall'indice dell'amministratore, crea questo metodo nella tua ModelAdminclasse e torna False. Esempio:

class MyModelAdmin(admin.ModelAdmin):
    ...
    def has_module_permission(self, request):
        return False

Purtroppo has_module_permissioninteressa l'intera app e non solo un modello. Quindi l'aggiunta di questo a un modello nell'app causa un 403 Forbidden nell'elenco dei modelli dell'app (/ admin / app_label /). Vedi django / contrib / admin / sites.py .
Fabian

1
@ Fabian Penso che sia un bug. L'ho chiesto sul canale IRC di Django e alcune persone concordano sul fatto che questo comportamento è indesiderato.
xyres

@Fabian Supponendo che la pagina dell'indice dell'amministratore sia ancora collegata a / admin / è possibile aggirare il bug con qualcosa di simile return request.path!='/admin/'. Sfortunatamente ciò riattiva quei modelli nell'elenco dei modelli dell'app.
ecp

Avevo aperto un ticket qui per questo bug. Questo è stato risolto qui . Dovrebbe essere incluso nella prossima versione, si spera.
xyres

In Django 1.11 il deep link funziona ancora ma l'entità non è elencata nella schermata di amministrazione principale
Csaba Toth

22

Ho lo stesso problema, ecco cosa mi è venuto in mente.

Come nella soluzione precedente: copia index.html da django nel tuo /admin/index.html e modificalo in questo modo:

{% for model in app.models %}
    {% if not model.perms.list_hide %}
    <tr>
    ...
    </tr>
    {% endif %}
{% endfor %}

E crea la sottoclasse ModelAdmin:

class HiddenModelAdmin(admin.ModelAdmin):
    def get_model_perms(self, *args, **kwargs):
        perms = admin.ModelAdmin.get_model_perms(self, *args, **kwargs)
        perms['list_hide'] = True
        return perms

Ora qualsiasi modello registrato con la sottoclasse HiddenModelAdmin non verrà visualizzato nell'elenco degli amministratori, ma sarà disponibile tramite il simbolo "più" in dettaglio:

class MyModelAdmin(HiddenModelAdmin):
    ...

admin.site.register(MyModel, MyModelAdmin)

1

Brutta soluzione: sovrascrivi il modello di indice dell'amministratore, ad esempio copia index.html da django nel tuo /admin/index.html e aggiungi qualcosa del genere:

{% for for model in app.models %}
    {% ifnotequal model.name "NameOfModelToHide" %}
    ...

1

Questo è un edificio alternativo sulla risposta di x0nix, e solo se sei felice di nascondere le righe con jquery.

Copia incollando dall'altra risposta la parte che ho riutilizzato

class HiddenModelAdmin(admin.ModelAdmin):
def get_model_perms(self, *args, **kwargs):
    perms = admin.ModelAdmin.get_model_perms(self, *args, **kwargs)
    perms['list_hide'] = True
    return perms

class MyModelAdmin(HiddenModelAdmin):
...

admin.site.register(MyModel, MyModelAdmin)

Quindi installa django-jquery e aggiungi il seguente blocco nel tuo /admin/index.htmlmodello:

{% extends "admin:admin/index.html" %}

{% block extrahead %}
    <script type="text/javascript" src="{{ STATIC_URL }}js/jquery.js"></script>
    {% if app_list %}
      <script type="text/javascript">
        $(function(){
          {% for app in app_list %}
            {% for model in app.models %}
                {% if model.perms.list_hide %}
                    $('div.app-{{ app.app_label }}').find('tr.model-{{ model.object_name|lower }}').hide();
                {% endif %}
            {% endfor %}
          {% endfor %}
        });
     </script>
   {% endif %}
{% endblock %}

Non è necessario copiare e incollare l'intero modello, basta estenderlo e sovrascrivere il extraheadblocco. Avrai bisogno di django-apptemplates per far funzionare quanto sopra.


0

Django 1.2 ha nuove istruzioni if, il che significa che la funzionalità desiderata può essere ottenuta solo sovrascrivendo admin / index.html

{% if model.name not in "Name of hidden model; Name of other hidden model" %}
    ...
{% endif %}

Questa è una cattiva soluzione, perché non si preoccupa degli amministratori multilingue. Ovviamente potresti aggiungere i nomi dei modelli in tutte le lingue supportate. È una buona soluzione perché non sovrascrive più di un aspetto delle funzioni principali di Django.

Ma prima di cambiare qualcosa, penso che la gente dovrebbe pensarci ...

Essenzialmente il problema è legato all'avere modelli che non si desidera utilizzare per più che aggiungere un'opzione a un menu a discesa di tanto in tanto. Potrebbe essere efficacemente aggirato creando una serie di autorizzazioni per gli utenti "non così avanzati" che si fanno prendere dal panico quando ci sono troppi modelli. Nel caso in cui siano necessarie modifiche ai modelli particolari, è sufficiente accedere con l '"account avanzato".


0

Avevo molti amministratori di modelli da registrare e nascondere, se vuoi una soluzione più DRY, questo ha funzionato per me (Django 1.10, Python 3.5)

# admin.py

def register_hidden_models(*model_names):
    for m in model_names:
        ma = type(
            str(m)+'Admin',
            (admin.ModelAdmin,),
            {
                'get_model_perms': lambda self, request: {}
            })
        admin.site.register(m, ma)

register_hidden_models(MyModel1, MyModel2, MyModel3)

Immagino che potresti inserirlo in una classe di utilità se desideri riutilizzarlo tra le app.


0

A partire da Django 1.8.18 , has_module_permission()ha ancora problemi. Quindi, nel nostro caso abbiamo utilizzato anche il file get_model_perms(). Allo stesso modo, dobbiamo nascondere il modello solo per un utente specifico, ma superuserdovrebbe essere in grado di accedere alla sua voce di indice.

class MyModelAdmin(admin.ModelAdmin):
    def get_model_perms(self, request):
        if not request.user.is_superuser:
            return {}
        return super(MyModelAdmin, self).get_model_perms(request)

admin.site.register(MyModel, MyModelAdmin)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.