2016-06-21 69 views
2

您好我有兩個型號,通過第三種模式m2m鏈接:如何使用prefetch_related在admin list_display中獲取自定義列的相關模型?

class Group(UsefulAbstractModel): 
    hotels = models.ManyToManyField(
     Hotel, 
     through='HotelDetails', 
     related_name='groups',) 

class Hotel(UsefulAbstractModel): 
    name = models.CharField(
     max_length=255,) 

class HotelDetails(models.Model): 
    hotel = models.ForeignKey(
      Hotel, 
      related_name='hotel_details',) 
    group = models.ForeignKey(
      Group, 
      related_name='hotel_details',) 
    num = models.IntegerField(
     validators=[ 
      MaxValueValidator(2), 
      MinValueValidator(1), ],) 

所有羣體有我需要管理員組接口,以顯示它的數字1和2。兩家酒店的聯繫。 我爲每個酒店兩個自定義列:

class GroupAdmin(admin.ModelAdmin): 

    def first_hotel(self, instance): 
     return instance.hotel_details.filter(num=1).first().hotel 

    def second_hotel(self, instance): 
     return instance.hotel_details.filter(num=1).first().hotel 

但對於每一個實例我現在有2個額外的查詢。
我試圖重寫queryset的方法,但在沒有幫助:

def queryset(self, request): 
    return super(GroupAdmin,self).queryset(request).prefetch_related('hotels') 
+0

除非您打算添加數字3,4等的酒店,否則有兩個外鍵「Group.hotel1」和「Group.hotel2」而不是多對多字段可能會更簡單。 – Alasdair

+0

@Alasdair是的,它可能會更好,並節省我很多時間。但是這個項目差不多完成了 –

回答

2

的問題是,你與filter(num=1)過濾預取結果。這會導致Django執行一個新的查詢。

您可以使用Prefetch對象來獲取正確的查詢集。請注意,您應該覆蓋模型管理員的get_queryset方法,而不是queryset

def get_queryset(self, request): 
    return super(GroupAdmin,self).get_queryset(request).prefetch_related(
     Prefetch('hotel_details', queryset=HotelDetails.objects.filter(num=1).select_related('hotel'), to_attr='hotel_details_num1'), 
    ) 

然後改變你的模型管理方法,以使用新的查詢集,例如:

def first_hotel(self, instance): 
    return instance.hotel_details_num1.first().hotel 

the docs更多成左右prefetch_relatedPrefetch對象。

+0

謝謝你的回答,但是我有錯誤,因爲'instance'對象沒有屬性,我們在'Prefetch'對象中定義 –

+0

我不明白你爲什麼得到'AttributeError'。只要你將查詢集與'Prefetch'對象一起使用,你應該能夠訪問'instance.hotel_details_num1'。 – Alasdair

+0

我找到解決方案。我使用'get_queryset'而不是'queryset',然後 我更改'select_related'查詢,因爲'Prefetch'對象返回列表,而不是queryset,所以我直接把它放在'queryset'屬性中,像這樣:'queryset = HotelDetails .objects.filter(num = 1).select_related()'我不明白爲什麼'queryset'方法不起作用,因爲我使用1.8版本。感謝您的幫助,請更新您的答案 –

相關問題