1

我有两个模型 - 合同和供应商。每个供应商都提供一种商品。这些定义如下:

class CommodityType(models.Model):
    name = models.CharField(max_length=64)

    def __unicode__(self):
        return self.name

class Supplier(models.Model):
    name = models.CharField(max_length=64)
    type = models.ForeignKey(CommodityType)

    def __unicode__(self):
        return self.name

    class Meta:
        ordering = ['type', 'name']

class Contract(models.Model):
    supplier = models.ForeignKey(Supplier)
    clientNumber = models.CharField(max_length=32)

    def __unicode__(self):
        return u'%s, %s' % (self.supplier, self.clientNumber)

我想Contracts在 Django 管理站点中有一个列表。对于每个Contracts,我希望Supplier显示引用的类型。因此,例如,如果相关供应商提供电力,那么我希望将其显示在Contracts.

但是,我似乎无法找到这是如何完成的。我找到了这个答案,但尝试这样做会给我一个 ImproperlyConfigured 错误。

如何才能做到这一点?

4

2 回答 2

1

您可能需要的是list_display

class ContractAdmin(admin.ModelAdmin):
    list_display('clientNumber', 'supplier')

admin.register(Contract, ContractAdmin)

__在管理员中允许外键,您可以使用此代码段

从片段:

from django.contrib import admin
from django.db import models

def getter_for_related_field(name, admin_order_field=None, short_description=None):
    """
        Create a function that can be attached to a ModelAdmin to use as a list_display field, e.g:
        client__name = getter_for_related_field('client__name', short_description='Client')
    """
    related_names = name.split('__')
    def getter(self, obj):
        for related_name in related_names:
            obj = getattr(obj, related_name)
        return obj
    getter.admin_order_field = admin_order_field or name
    getter.short_description = short_description or related_names[-1].title().replace('_',' ')
    return getter

class RelatedFieldAdminMetaclass(admin.ModelAdmin.__metaclass__):
    """
        Metaclass used by RelatedFieldAdmin to handle fetching of related field values.
        We have to do this as a metaclass because Django checks that list_display fields are supported by the class.
    """
    def __getattr__(self, name):
        if '__' in name:
            getter = getter_for_related_field(name)
            setattr(self, name, getter) # cache so we don't have to do this again
            return getter
        raise AttributeError # let missing attribute be handled normally

class RelatedFieldAdmin(admin.ModelAdmin):
    """
        Version of ModelAdmin that can use related fields in list_display, e.g.:
        list_display = ('address__city', 'address__country__country_code')
    """
    __metaclass__ = RelatedFieldAdminMetaclass
    def queryset(self, request):
        qs = super(RelatedFieldAdmin, self).queryset(request)

        # include all related fields in queryset
        select_related = [field.rsplit('__',1)[0] for field in self.list_display if '__' in field]

        # Include all foreign key fields in queryset.
        # This is based on ChangeList.get_query_set().
        # We have to duplicate it here because select_related() only works once.
        # Can't just use list_select_related because we might have multiple__depth__fields it won't follow.
        model = qs.model
        for field_name in self.list_display:
            try:
                field = model._meta.get_field(field_name)
            except models.FieldDoesNotExist:
                continue
            if isinstance(field.rel, models.ManyToOneRel):
                select_related.append(field_name)

        return qs.select_related(*select_related)





#### USAGE ####
class FooAdmin(RelatedFieldAdmin):
    # these fields will work automatically:
    list_display = ('address__phone','address__country__country_code','address__foo')

    # ... but you can also define them manually if you need to override short_description:
    address__foo = getter_for_related_field('address__foo', short_description='Custom Name')
于 2013-06-20T15:24:50.640 回答
0

最近发布了一个名为django-related-admin的库,它可以让您在 Django admin 更改列表中list_display使用 '__' 如此轻松地使用外键属性,具体针对这个问题,如何在admin.py模块中使用该库如下:

管理员.py

from related_admin import RelatedFieldAdmin
from related_admin import getter_for_related_field

class ContractAdmin(RelatedFieldAdmin):
    # these fields will work automatically (and boolean fields will display an icon):
    list_display = ('clientNumber','supplier__type__name')

    # or you can also define them manually if you need to override short_description or boolean parameter:
    supplierType = getter_for_related_field('supplier__type__name', short_description='supplier type', boolean=False)
于 2022-02-11T14:26:10.213 回答