427 Stimmen

Kann "list_display" in einem Django ModelAdmin Attribute von ForeignKey-Feldern anzeigen?

Ich habe eine Person Modell, das eine Fremdschlüsselbeziehung zu Book die eine Reihe von Feldern hat, aber ich bin am meisten besorgt über author (ein Standard-CharField).

Davon abgesehen, sind in meinem PersonAdmin Modell, möchte ich Folgendes anzeigen book.author mit list_display :

class PersonAdmin(admin.ModelAdmin):
    list_display = ['book.author',]

Ich habe alle offensichtlichen Methoden dafür ausprobiert, aber nichts scheint zu funktionieren.

Irgendwelche Vorschläge?

671voto

imjoevasquez Punkte 13261

Eine weitere Möglichkeit ist das Nachschlagen von Informationen wie:

class UserAdmin(admin.ModelAdmin):
    list_display = (..., 'get_author')

    def get_author(self, obj):
        return obj.book.author
    get_author.short_description = 'Author'
    get_author.admin_order_field = 'book__author'

Seit Django 3.2 können Sie mit display() Dekorateur:

class UserAdmin(admin.ModelAdmin):
    list_display = (..., 'get_author')

    @display(ordering='book__author', description='Author')
    def get_author(self, obj):
        return obj.book.author

207voto

Will Punkte 10696

Trotz all der großartigen Antworten oben und weil ich neu in Django bin, steckte ich immer noch fest. Hier ist meine Erklärung von einem sehr Neuling Perspektive.

models.py

class Author(models.Model):
    name = models.CharField(max_length=255)

class Book(models.Model):
    author = models.ForeignKey(Author)
    title = models.CharField(max_length=255)

admin.py (Falscher Weg) - Sie denken, es würde funktionieren, wenn Sie 'model__field' als Referenz verwenden, aber das tut es nicht

class BookAdmin(admin.ModelAdmin):
    model = Book
    list_display = ['title', 'author__name', ]

admin.site.register(Book, BookAdmin)

admin.py (Korrekter Weg) - So referenzieren Sie einen Fremdschlüsselnamen auf Django-Art

class BookAdmin(admin.ModelAdmin):
    model = Book
    list_display = ['title', 'get_name', ]

    def get_name(self, obj):
        return obj.author.name
    get_name.admin_order_field  = 'author'  #Allows column order sorting
    get_name.short_description = 'Author Name'  #Renames column head

    #Filtering on side - for some reason, this works
    #list_filter = ['title', 'author__name']

admin.site.register(Book, BookAdmin)

Weitere Informationen finden Sie unter dem Link Django-Modell ici

76voto

Hunger Punkte 4777

Bitte beachten Sie, dass das Hinzufügen der get_author Funktion würde die Anzeige der Liste in der Verwaltung verlangsamen, da die Anzeige jeder Person eine SQL-Abfrage erfordern würde.

Um dies zu vermeiden, müssen Sie Folgendes ändern get_queryset Methode in PersonAdmin, zum Beispiel:

def get_queryset(self, request):
    return super(PersonAdmin,self).get_queryset(request).select_related('book')

Vorher: 73 Abfragen in 36,02 ms (67 doppelte Abfragen in der Verwaltung)

Nach: 6 Abfragen in 10,81ms

74voto

Arjen Punkte 1301

Wie die anderen habe auch ich mich für abrufbare Wertpapiere entschieden. Aber sie haben einen Nachteil: Man kann nicht auf ihnen bestellen. Zum Glück gibt es dafür eine Lösung:

Django >= 1.8

def author(self, obj):
    return obj.book.author
author.admin_order_field  = 'book__author'

Django < 1.8

def author(self):
    return self.book.author
author.admin_order_field  = 'book__author'

45voto

Cesar Canassa Punkte 16112

Für Django >= 3.2

Der richtige Weg, dies mit Django 3.2 oder höher zu tun, ist die Verwendung der Display-Dekorateur

class BookAdmin(admin.ModelAdmin):
    model = Book
    list_display = ['title', 'get_author_name']

    @admin.display(description='Author Name', ordering='author__name')
    def get_author_name(self, obj):
        return obj.author.name

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X