Django Admin, verstecke ein Modell

84

Auf der Stammseite der Administrationsseite, auf der registrierte Modelle angezeigt werden, möchte ich mehrere Modelle ausblenden, die beim Django-Administrator registriert sind.

Wenn ich die Registrierung direkt aufhebe, kann ich keine neuen Datensätze hinzufügen, da das neue Symbol "+" verschwindet.

Wie kann das gemacht werden?

Hellnar
quelle

Antworten:

122

Basierend auf der Antwort von x0nix habe ich einige Experimente durchgeführt. Es scheint, als würde die Rückgabe eines leeren Diktats von get_model_permsdas Modell aus index.html ausschließen, während Sie weiterhin Instanzen direkt bearbeiten können.

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)
shaunsephton
quelle
Einverstanden. Nur das ist ein Problem, wenn ich den Code nicht ändern möchte. Ich meine, ich habe eine Basis-App, die ich von Abhängigkeiten von anderen Apps fernhalten möchte. Ich behalte diese Abhängigkeiten in einer abgeleiteten projektspezifischen App. Jetzt möchte ich, dass die Administrationsoberfläche nur die abgeleitete App anzeigt, nicht die Basis-App. Für Django muss die Basis-App in settings / INSTALLED_APPS aufgeführt sein, damit die abgeleitete App funktioniert. Natürlich sollte die Basis-App nicht angezeigt werden, aber gleichzeitig möchte ich sie nicht unverändert und wiederverwendbar lassen. Siehe [hier] ( Stack Exchange / Fragen / 13923968 /).
Sven
6
Ein kürzerer Weg:get_model_perms = lambda self, req: {}
Tigran Saluev
2
Was ist, wenn ich ein Modell vor einem bestimmten userAdmin ausblenden möchte?
Alireza Sanaee
Seien Sie vorsichtig mit dieser Lösung - obwohl der Link verschwindet, kann der Benutzer wie folgt zum Objekt selbst springen: / admin / main / comment / 2333 / change /
goodgrief
31

Für Django 1.8 und höher

Seit Django 1.8 ModelAdmingibt es eine neue Methode, has_module_permission()die für die Anzeige eines Modells im Admin-Index verantwortlich ist.

Um ein Modell vor dem Admin-Index auszublenden, erstellen Sie einfach diese Methode in Ihrer ModelAdminKlasse und kehren Sie zurück False. Beispiel:

class MyModelAdmin(admin.ModelAdmin):
    ...
    def has_module_permission(self, request):
        return False
Xyres
quelle
has_module_permissionBetrifft leider die gesamte App und nicht nur das eine Modell. Wenn Sie dies also einem Modell in der App hinzufügen, wird in der App-Modellliste (/ admin / app_label /) ein 403 Forbidden angezeigt. Siehe django / contrib / admin / sites.py .
Fabian
1
@ Fabian Ich denke, das ist ein Fehler. Ich habe dies auf dem IRC-Kanal von Django gefragt, und einige Leute dort sind sich einig, dass dieses Verhalten unerwünscht ist.
Xyres
@Fabian Angenommen, die Admin-Indexseite enthält weiterhin Links zu / admin /. Es ist möglich, diesen Fehler durch so etwas wie zu umgehen return request.path!='/admin/'. Leider werden diese Modelle in der App-Modellliste wieder aktiviert.
ecp
Ich hatte hier ein Ticket für diesen Fehler geöffnet . Dies wurde hier behoben . Es sollte hoffentlich in der nächsten Version enthalten sein.
Xyres
In Django 1.11 funktioniert der Deep Link immer noch, aber die Entität ist nicht auf dem Hauptbildschirm des Administrators aufgeführt
Csaba Toth
22

Habe das gleiche Problem, hier was ich mir ausgedacht habe.

Kopieren Sie wie in der vorherigen Lösung index.html von django in Ihre Datei /admin/index.html und ändern Sie es wie folgt:

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

Und erstellen Sie die ModelAdmin-Unterklasse:

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

Jetzt wird jedes Modell, das bei der HiddenModelAdmin-Unterklasse registriert ist, nicht in der Administratorliste angezeigt, sondern ist im Detail über das Pluszeichen verfügbar:

class MyModelAdmin(HiddenModelAdmin):
    ...

admin.site.register(MyModel, MyModelAdmin)
x0nix
quelle
1

Hässliche Lösung: Überschreiben Sie die Admin-Indexvorlage, dh kopieren Sie index.html von django in Ihre /admin/index.html und fügen Sie Folgendes hinzu:

{% for for model in app.models %}
    {% ifnotequal model.name "NameOfModelToHide" %}
    ...
alex vasi
quelle
1

Dies ist ein alternatives Gebäude, das auf der Antwort von x0nix aufbaut, und nur dann, wenn Sie glücklich sind, die Zeilen mit jquery zu verstecken.

Kopieren Sie das Einfügen von der anderen Antwort auf den Teil, den ich wiederverwendet habe

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)

Installieren Sie dann django-jquery und fügen Sie der /admin/index.htmlVorlage den folgenden Block hinzu :

{% 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 %}

Sie müssen nicht die gesamte Vorlage kopieren, sondern nur erweitern und den extraheadBlock überschreiben . Sie benötigen Django-Apptemplates, damit das oben genannte funktioniert.

Panos
quelle
0

Django 1.2 verfügt über neue if-Anweisungen, was bedeutet, dass die gewünschte Funktion nur durch Überschreiben von admin / index.html erhalten werden kann

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

Dies ist eine schlechte Lösung, da es sich nicht um mehrsprachige Administratoren handelt. Sie können natürlich die Namen der Modelle in allen unterstützten Sprachen hinzufügen. Dies ist eine gute Lösung, da nicht mehr als ein Aspekt der Kernfunktionen von Django überschrieben wird.

Aber bevor ich etwas ändere, denke ich, sollten die Leute darüber nachdenken ...

Im Wesentlichen hängt das Problem damit zusammen, dass Modelle vorhanden sind, die nicht länger verwendet werden sollen, als hin und wieder eine Option zu einem Dropdown-Menü hinzuzufügen. Es könnte effektiv umgangen werden, indem eine Reihe von Berechtigungen für "nicht so fortgeschrittene" Benutzer erstellt werden, die in Panik geraten, wenn zu viele Modelle vorhanden sind. Falls Änderungen an den jeweiligen Modellen erforderlich sind, können Sie sich einfach mit dem "erweiterten Konto" anmelden.

benjaoming
quelle
0

Ich musste viele Modelladministratoren registrieren und ausblenden. Wenn Sie eine trockenere Lösung wünschen, funktionierte dies für mich (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)

Ich denke, Sie könnten es in eine Utility-Klasse rollen, wenn Sie es für mehrere Apps wiederverwenden möchten.

Murraybiscuit
quelle
0

Ab Django 1.8.18 gibt es has_module_permission()noch Probleme . Also haben wir in unserem Fall auch die verwendet get_model_perms(). Ebenso müssen wir das Modell nur für einen bestimmten Benutzer ausblenden, aber der superusersollte auf seinen Indexeintrag zugreifen können.

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)
Ranel Padon
quelle