2008-12-29 7 views
28

Sagen wir, ich meine Pizza-Anwendung mit Topping und Pizza-Klassen haben und sie zeigen in Django Admin wie folgt aus:Reihenfolge admin.ModelAdmin Objekte in Django Admin

PizzaApp 
- 
Toppings  >>>>>>>>>>  Add/Change 

Pizzas  >>>>>>>>>>  Add/Change 

Aber ich möchte, dass sie wie folgt aus:

PizzaApp 
- 
Pizzas  >>>>>>>>>>  Add/Change 

Toppings  >>>>>>>>>>  Add/Change 

Wie konfiguriere ich das in meinem admin.py?

Antwort

11

Dies ist eigentlich ganz am Ende von Part 2 of the Django Tutorial bedeckt.

Hier ist der entsprechende Abschnitt:

Anpassen der Admin-Index-Seite

Auf eine ähnliche Notiz, könnten Sie zu wollen das Look and Feel des Django Admin-Index-Seite anpassen.

Standardmäßig zeigt sie alle Apps in INSTALLED_APPS die mit der Admin-Anwendung registriert worden ist, in alphabetischer Reihenfolge. Möglicherweise möchten Sie wesentliche Änderungen an der Layout vornehmen. Immerhin ist der Index wahrscheinlich die wichtigste Seite von der Admin, und es sollte einfach zu verwenden.

Die Vorlage zum Anpassen ist admin/index.html. (Machen Sie dasselbe wie bei admin/base_site.html im vorherigen Abschnitt -. Kopieren Sie sie aus dem Standard- Verzeichnis Ihrer benutzerdefinierten Vorlage Verzeichnis) Bearbeiten Sie die Datei, und Sie werden sehen verwendet es eine Template-Variable genannt app_list.Diese Variable enthält jede installierte Django App. Anstatt zu verwenden, können Sie Links zu objektspezifischen Admin-Seiten in fest kodieren, wie auch immer Sie es für am besten halten.

+3

Das ist gut zu wissen, aber ich denke, die Frage im Zusammenhang mit ein paar Model-Klassen in der gleichen installierten App. Das Ändern der Reihenfolge der Apps würde Ihnen nicht helfen, wenn Sie die Reihenfolge Ihrer Modellklassen innerhalb einer einzelnen App ändern möchten. – Jeff

+0

Es ist gut zu denken. Sie müssen irgendwo aufgelistet sein und vielleicht muss ich dort nur einen Sortierfilter anwenden. Ich werde mir das morgen ansehen (europäische Zeitzone hier ...) Danke –

0

Dies ist nur eine wilde Stich im Dunkeln, aber gibt es eine Chance, dass die Reihenfolge, in der Sie admin.site.register (< Model-Klasse>, < ModelAdmin Klasse>) aufrufen kann die Reihenfolge der Anzeige? Eigentlich bezweifle ich, dass das funktionieren würde, weil ich glaube, dass Django eine Registrierung der Model -> ModelAdmin-Objekte führt, die als Standard-Python-Wörterbuch implementiert sind, das die Iterationsreihenfolge nicht aufrecht erhält.

Wenn sich das nicht so verhält, wie Sie es möchten, können Sie immer mit der Quelle in django/contrib/admin spielen. Wenn Sie die Iterationsreihenfolge beibehalten möchten, können Sie das _registry-Objekt in der AdminSite-Klasse (in admin/sites.py) durch ein UserDict oder DictMixin ersetzen, das die Reihenfolge für die Reihenfolge der Schlüssel beibehält. (Aber bitte nehmen Sie diesen Ratschlag mit einem Körnchen Salz, da ich diese Art von Änderungen nie selbst gemacht habe, und ich mache nur eine begründete Vermutung darüber, wie Django über die Sammlung von ModelAdmin-Objekten iteriert. Ich denke, dass django/contrib /admin/sites.py ist der Ort, um nach diesem Code zu suchen, und die AdminSite-Klasse und register() - und insbesondere die index() -Methoden sind genau das, was Sie wollen.)

Offensichtlich wäre das Schönste hier ein einfache Option, die Sie in Ihrem eigenen Modul /admin.py angeben können. Ich bin sicher, das ist die Art von Antwort, die Sie erhofften. Ich bin mir nicht sicher, ob diese Möglichkeiten existieren.

+0

Ja, ich hatte gehofft, diese Art von Antwort zu erhalten und fürchte diese Art. Ich denke, du hast recht, zumindest aus dem, was ich in den Dokumenten finden konnte. Ich denke, ich werde das so lassen wie es ist. Ich möchte meine eigene Version von Django nicht beibehalten. –

0

Meine Lösung war, Unterklassen von django.contrib.admin.sites.AdminSite und django.contrib.admin.options.ModelAdmin zu machen.

Ich tat dies, damit ich einen aussagekräftigeren Titel für jede App anzeigen und das Aussehen der Modelle in jeder App bestellen konnte. Also habe ich ein dict in meinem settings.py, das app_labels beschreibenden Namen und der Reihenfolge, in der sie erscheinen sollten, zuordnet. Die Modelle sind nach einem ordinalen Feld geordnet, das ich in jedem ModelAdmin bei der Registrierung auf der Admin-Seite bereitstelle.

Obwohl die Erstellung eigener Unterklassen von AdminSite und ModelAdmin in den Dokumenten empfohlen wird, sieht meine Lösung am Ende wie ein hässlicher Hack aus.

26

Eine Abhilfe, die Sie versuchen können, Ihre models.py wird zwicken wie folgt:

class Topping(models.Model): 
    . 
    . 
    . 
    class Meta: 
     verbose_name_plural = "2. Toppings" 

class Pizza(models.Model): 
    . 
    . 
    . 
    class Meta: 
     verbose_name_plural = "1. Pizzas" 

nicht sicher, ob sie gegen die besten Praktiken Djangos ist, aber es funktioniert (mit django Stamm getestet).

Viel Glück!

PS: Entschuldigung, wenn diese Antwort zu spät gepostet wurde, aber es kann anderen in Zukunft ähnliche Situationen helfen.

+0

Das ist was ich benutze. Obwohl dies ein Workaround ist, ist es der einfachste Ansatz. – ePi272314

+3

traurig. es würde sagen "3 1. Pizzen", wenn Sie 3 Pizza-Einträge haben. – user3526

12

Wenn Sie wollen, dass diese nur in 10 Sekunden lösen verwenden Räume in verbose_name_plural, zum Beispiel:

class Topping(models.Model): 
    class Meta: 
     verbose_name_plural = " Toppings" # 2 spaces 

class Pizza(models.Model): 
    class Meta: 
     verbose_name_plural = " Pizzas" # 1 space 

Natürlich ist es nicht ellegant ist, aber für eine Weile arbeiten, bevor wir eine bessere Lösung zu bekommen.

+0

Funktioniert im neuesten Django 1.11. Beachten Sie, dass die Leerzeichen am Anfang nicht vom Browser gerendert werden, so dass es im Titel keine sichtbaren Auswirkungen hat. Beachten Sie auch, dass dies mit 'AppConfig'-Klassen funktioniert, um auch die Anwendungsbereiche neu zu ordnen. – Mrdev

3

Auch ein kleiner Code geschnippt, der 'Django Admin-Index benutzerdefinierte App & Modell Bestellung' genannt wird, kann verwendet werden. Das Snippet löst das Problem mit nur 3 einfachen Bearbeitungen.

Hier sehen Sie sich die Details an. http://djangosnippets.org/snippets/2613/

17

Ich schaffte es schließlich, es zu tun dank diesen Django snippet, man muss nur die ADMIN_REORDER Einstellung bewusst sein:

ADMIN_REORDER = (
    ('app1', ('App1Model1', 'App1Model2', 'App1Model3')), 
    ('app2', ('App2Model1', 'App2Model2')), 
) 

app1 darf nicht mit dem Projektnamen vorangestellt werden, dh app1 anstelle von mysite.app1.

+4

Das wäre großartig, wenn es tatsächlich funktioniert hätte. – thnee

+0

Nun, dies funktionierte auf Version 1.3, was ist das Problem, vor dem Sie stehen? – Emmanuel

+0

Die Reihenfolge ändert sich einfach nicht. – thnee

2

Wenn Sie Suit für die AdminSite verwenden, können Sie die Menüanpassung mit der menu tag vornehmen.

+0

Mit dem Menü-Tag, gelang es mir nur das Aussehen des linken Menüs zu ändern. – raratiru

5

Hier ist das Snippet Emmanuel verwendet, aktualisiert Django 1.8:

In templatetags/admin_reorder.py:

from django import template 
from django.conf import settings 
from collections import OrderedDict 

register = template.Library() 

# from http://www.djangosnippets.org/snippets/1937/ 
def register_render_tag(renderer): 
    """ 
    Decorator that creates a template tag using the given renderer as the 
    render function for the template tag node - the render function takes two 
    arguments - the template context and the tag token 
    """ 
    def tag(parser, token): 
     class TagNode(template.Node): 
      def render(self, context): 
       return renderer(context, token) 
     return TagNode() 
    for copy_attr in ("__dict__", "__doc__", "__name__"): 
     setattr(tag, copy_attr, getattr(renderer, copy_attr)) 
    return register.tag(tag) 

@register_render_tag 
def admin_reorder(context, token): 
    """ 
    Called in admin/base_site.html template override and applies custom ordering 
    of apps/models defined by settings.ADMIN_REORDER 
    """ 
    # sort key function - use index of item in order if exists, otherwise item 
    sort = lambda order, item: (order.index(item), "") if item in order else (
     len(order), item) 
    if "app_list" in context: 
     # sort the app list 
     order = OrderedDict(settings.ADMIN_REORDER) 
     context["app_list"].sort(key=lambda app: sort(order.keys(), 
      app["app_url"].strip("/").split("/")[-1])) 
     for i, app in enumerate(context["app_list"]): 
      # sort the model list for each app 
      app_name = app["app_url"].strip("/").split("/")[-1] 
      if not app_name: 
       app_name = app["name"].lower() 
      model_order = [m.lower() for m in order.get(app_name, [])] 
      context["app_list"][i]["models"].sort(key=lambda model: 
      sort(model_order, model["admin_url"].strip("/").split("/")[-1])) 
    return "" 

In Einstellungen.py:

ADMIN_REORDER = (
    ('app1', ('App1Model1', 'App1Model2', 'App1Model3')), 
    ('app2', ('App2Model1', 'App2Model2')), 
) 

(Ihre eigenen App-Namen einfügen hier Admin platzieren werden Anwendungen oder Modelle am Ende der Liste fehlt, so lange, wie Sie mindestens zwei Modelle in jeder App-Liste..)

in Ihrer Kopie von base_site.html:

{% extends "admin/base.html" %} 
{% load i18n admin_reorder %} 

{% block title %}{{ title }} | {% trans 'Django site admin' %}{% endblock %} 

{% block branding %} 
{% admin_reorder %} 
<h1 id="site-name">{% trans 'Django administration' %}</h1> 
{% endblock %} 

{% block nav-global %}{% endblock %} 
+0

danke es funktioniert auch mit Django 1.10 :) –

1

Ich war auf der Suche nach einer einfachen Lösung, wo ich die Apps nach ihrem Namen im Admin-Panel bestellen konnte. Ich kam mit dem folgenden Template-Tag auf:

from django import template 
from django.conf import settings 
register = template.Library() 

@register.filter 
def sort_apps(apps): 
    apps.sort(
     key = lambda x: 
     settings.APP_ORDER.index(x['app_label']) 
     if x['app_label'] in settings.APP_ORDER 
     else len(apps) 
    ) 
    print [x['app_label'] for x in apps] 
    return apps 

Dann nur templates/admin/index.html außer Kraft setzen und dass die Template-Tag hinzu:

{% extends "admin/index.html" %} 
{% block content %} 
{% load i18n static sort_apps %} 
<div id="content-main"> 

{% if app_list %} 
    {% for app in app_list|sort_apps %} 
     <div class="app-{{ app.app_label }} module"> 
     <table> 
     <caption> 
      <a href="{{ app.app_url }}" class="section" title="{% blocktrans with name=app.name %}Models in the {{ name }} application{% endblocktrans %}">{{ app.name }}</a> 
     </caption> 
     {% for model in app.models %} 
      <tr class="model-{{ model.object_name|lower }}"> 
      {% if model.admin_url %} 
       <th scope="row"><a href="{{ model.admin_url }}">{{ model.name }}</a></th> 
      {% else %} 
       <th scope="row">{{ model.name }}</th> 
      {% endif %} 

      {% if model.add_url %} 
       <td><a href="{{ model.add_url }}" class="addlink">{% trans 'Add' %}</a></td> 
      {% else %} 
       <td>&nbsp;</td> 
      {% endif %} 

      {% if model.admin_url %} 
       <td><a href="{{ model.admin_url }}" class="changelink">{% trans 'Change' %}</a></td> 
      {% else %} 
       <td>&nbsp;</td> 
      {% endif %} 
      </tr> 
     {% endfor %} 
     </table> 
     </div> 
    {% endfor %} 
{% else %} 
    <p>{% trans "You don't have permission to edit anything." %}</p> 
{% endif %} 
</div> 
{% endblock %} 

Dann maßgeschneiderte die APP_ORDER in settings.py:

APP_ORDER = [ 
    'app1', 
    'app2', 
    # and so on... 
] 

Es funktioniert gut auf Django 1.10

+0

Ja, schöne Arbeit in Django 2.0. Für initialisieren Sie können mit 'libraries' Schlüssel in' VORLAGEN [ 'OPTIONS'] 'dict wie folgt aus: ' '' 'Bibliotheken': { 'sort_apps': 'src.apps.utils.templatetags.customize_tags', } '' ' Ohne zu INSTALLED_APPS hinzuzufügen – teror4uks