Frage

Ich habe ein Person Modell, das eine Fremdschlüsselbeziehung Book hat, die eine Anzahl von Feldern hat, aber ich bin sehr besorgt über author (ein Standard CharField).

Mit diesem wird gesagt, in meinem PersonAdmin Modell, ich möchte book.author anzuzeigen list_display mit:

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

Ich habe alle offensichtlichen Methoden versucht, so zu tun, aber nichts scheint zu funktionieren.

Irgendwelche Vorschläge?

War es hilfreich?

Lösung

Als weitere Option können Sie aussehen ups tun:

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'

Andere Tipps

Trotz aller großen Antworten oben und wegen mir Django neu zu sein, war ich immer noch fest. Hier ist meine Erklärung von einer sehr newbie 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) - denken Sie es mithilfe von 'model__field' zu Referenz funktionieren würde, aber es funktioniert nicht

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

admin.site.register(Book, BookAdmin)

admin.py (richtiger Weg) - das ist, wie Sie einen Fremdschlüssel Namen des Django Weges Referenz

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)

Für weitere Referenz finden Sie in der Django-Modell Link

Wie der Rest ging ich mit Callables auch. Aber sie haben einen Nachteil: Standardmäßig können Sie nicht auf sie bestellen. Glücklicherweise gibt es eine Lösung dafür:

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

Bitte beachten Sie, dass die get_author Funktion Zugabe würde die list_display im Admin verlangsamen, weil jede Person zeigen würde eine SQL-Abfrage machen.

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

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

Vor 73 Abfragen in 36.02ms (67 duplizierte Anfragen in admin)

     

Nach 6 Abfragen in 10.81ms

Nach der Dokumentation, können Sie nur die __unicode__ Darstellung eines ForeignKey angezeigt werden:

http://docs.djangoproject.com/en / dev / ref / contrib / admin / # list-Anzeige

Es scheint seltsam, dass es nicht das 'book__author' Stil Format nicht unterstützt, die überall in dem DB-API verwendet wird.

Es stellt sich heraus gibt es ein Ticket für diese Funktion , die gekennzeichnet ist als würde nicht beheben.

Sie können zeigen, was Sie in Listendarstellung wollen durch eine aufrufbare verwenden. Es würde wie folgt aussehen:

def book_author(object):
  return object.book.author

class PersonAdmin(admin.ModelAdmin):
  list_display = [book_author,]

Ich habe gerade gebucht einen Schnipsel, die admin.ModelAdmin Unterstützung '__' Syntax macht:

http://djangosnippets.org/snippets/2887/

So können Sie tun:

class PersonAdmin(RelatedFieldAdmin):
    list_display = ['book__author',]

Dies ist im Grunde nur tun, die gleiche Sache in den anderen Antworten beschrieben, aber es kümmert sich automatisch um (1) Einstellung admin_order_field (2) Einstellung short_description und (3) Modifizieren der queryset eine Datenbank Hit für jede Zeile zu vermeiden.

ist das man schon akzeptiert, aber wenn es keine andere Dummies gibt (wie ich), die nicht sofort von der bekommen hat derzeit Antwort akzeptiert, ist hier ein bisschen mehr Detail.

Die Modellklasse durch die ForeignKey verwiesen braucht eine __unicode__ Methode darin zu haben, wie hier:

class Category(models.Model):
    name = models.CharField(max_length=50)

    def __unicode__(self):
        return self.name

Das machte den Unterschied für mich, und soll auf das oben beschriebene Szenario anzuwenden. Dies funktioniert auf Django 1.0.2.

, wenn Sie es in Inline versuchen, Sie werden nicht erfolgreich sein, wenn:

in Ihrem inline:

class AddInline(admin.TabularInline):
    readonly_fields = ['localname',]
    model = MyModel
    fields = ('localname',)

in Ihrem Modell (MyModel):

class MyModel(models.Model):
    localization = models.ForeignKey(Localizations)

    def localname(self):
        return self.localization.name

Wenn Sie eine Menge Beziehung Attributfeldern in list_display verwenden und nicht möchten, dass eine Funktion erstellen (und es ist Attribute) für jeden, eine unbefestigte, aber einfache Lösung, um die ModelAdmin instace __getattr__ Methode außer Kraft setzen würde, die Callables Schaffung auf die Fliege:

class DynamicLookupMixin(object):
    '''
    a mixin to add dynamic callable attributes like 'book__author' which
    return a function that return the instance.book.author value
    '''

    def __getattr__(self, attr):
        if ('__' in attr
            and not attr.startswith('_')
            and not attr.endswith('_boolean')
            and not attr.endswith('_short_description')):

            def dyn_lookup(instance):
                # traverse all __ lookups
                return reduce(lambda parent, child: getattr(parent, child),
                              attr.split('__'),
                              instance)

            # get admin_order_field, boolean and short_description
            dyn_lookup.admin_order_field = attr
            dyn_lookup.boolean = getattr(self, '{}_boolean'.format(attr), False)
            dyn_lookup.short_description = getattr(
                self, '{}_short_description'.format(attr),
                attr.replace('_', ' ').capitalize())

            return dyn_lookup

        # not dynamic lookup, default behaviour
        return self.__getattribute__(attr)


# use examples    

@admin.register(models.Person)
class PersonAdmin(admin.ModelAdmin, DynamicLookupMixin):
    list_display = ['book__author', 'book__publisher__name',
                    'book__publisher__country']

    # custom short description
    book__publisher__country_short_description = 'Publisher Country'


@admin.register(models.Product)
class ProductAdmin(admin.ModelAdmin, DynamicLookupMixin):
    list_display = ('name', 'category__is_new')

    # to show as boolean field
    category__is_new_boolean = True

Wie Kern hier

aufrufbare besondere Attribute wie boolean und short_description müssen definiert werden als ModelAdmin Attribute, zB book__author_verbose_name = 'Author name' und category__is_new_boolean = True.

Das aufrufbar admin_order_field Attribut wird automatisch definiert.

Vergessen Sie nicht, die list_select_related Attribut in Ihrem ModelAdmin zu machen Django aditional Abfragen zu vermeiden.

Es ist ein sehr einfaches Paket in PyPI zur Verfügung zu verwenden, die Griffe genau das: django- verwandte-admin . Sie können auch den Code in GitHub .

Mit diesem, was Sie erreichen wollen, ist so einfach wie:

class PersonAdmin(RelatedFieldAdmin):
    list_display = ['book__author',]

Die beiden Links enthalten Ausführliche Informationen zur Installation und Nutzung, so will ich sie hier nicht einfügen, falls sie sich ändern.

So wie eine Randnotiz, wenn Sie bereits etwas anderes als model.Admin verwenden sind (zum Beispiel war ich mit SimpleHistoryAdmin statt), können Sie dies tun: class MyAdmin(SimpleHistoryAdmin, RelatedFieldAdmin)

.

AlexRobbins' Antwort war für mich, mit der Ausnahme, dass die ersten beiden Linien im Modell sein müssen (vielleicht ist dies angenommen wurde?), Und soll selbst verweisen:

def book_author(self):
  return self.book.author

Dann wird der Admin-Teil funktioniert gut.

Ich ziehe es so aus:

class CoolAdmin(admin.ModelAdmin):
    list_display = ('pk', 'submodel__field')

    @staticmethod
    def submodel__field(obj):
        return obj.submodel.field
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top