2013-06-20 79 views
1

我有兩個模型 - Contract和Supplier。每個供應商提供一種商品。這些定義如下:從Django Admin站點顯示的參考模型中獲取字段的值

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的清單中顯示。

但是,我似乎無法找到如何做到這一點。我發現this answer,但試圖給我一個錯誤配置錯誤。

這怎麼辦?

回答

1

你可能需要的是list_display

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

admin.register(Contract, ContractAdmin) 

爲了讓__在管理外鍵,您可以使用this snippet

從片段:

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') 
+0

你看了最後我的問題的一部分?我想顯示引用供應商的**字段**,而不是供應商自己。 – Shade

+0

編輯有幫助嗎? – karthikr

+0

是的,太棒了!這正是我需要的:)謝謝。也許你可以澄清最後的部分以便將來參考。 – Shade