2016-06-21 1 views
2

こんにちは、私は3番目のモデルを通じてm2mリンクを持つ2つのモデルがあります: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), ],) 

すべてのグループは、私がadminグループ・インタフェースに表示する必要がある番号1と2を持つ2つのホテルのリンクがあります。 私は各ホテルには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,5などのホテルを追加する予定がない限り、多対多フィールドの代わりに2つの外部キー「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 

prefetch_relatedPrefetchオブジェクトに多くのためthe docsを参照してください。

+0

回答ありがとうございますが、 'instance'オブジェクトには属性がありません.' Prefetch'オブジェクトで定義しています。 –

+0

なぜあなたは' AttributeError'を取得しているのか分かりません。 'Prefetch'オブジェクトでクエリーセットを使用する限り、' instance.hotel_details_num1'にアクセスできるはずです。 – Alasdair

+0

解決策が見つかりました。私は 'queryset'の代わりに' get_queryset'メソッドを使用しました。 'Prefetch'オブジェクトはクエリーセットではなくリストを返すので、' select_related'クエリーを変更しましたので、 'queryset'アトリビュートに直接入れます:' queryset = HotelDetails .objects.filter(num = 1).select_related() 'なぜ私が1.8バージョンを使用しているので、' queryset'メソッドがうまくいかないのか分かりません。ありがとう、助けてくれて、あなたの答えを更新してください。 –

関連する問題