2009-09-02 8 views
1

私の醜い英語のために私を失礼です!Django:1つの公開写真を含むすべてのギャラリーを取得少なくとも

は、これらの非常に単純なモデルを想像してみて:

class Photo(models.Model): 
    is_public = models.BooleanField('Public', default=False) 

class Gallery(models.Model): 
    photos = models.ManyToManyField('Photos', related_name='galleries', null=True, blank=True) 

私は少なくともつのパブリック写真(および可能な場合は公開写真が多数含まれていphotos__count属性を追加すること)を含むすべてのGalleryのインスタンスを選択する必要があります。

が、私はこのクエリを試してみました:

Gallery.objects.all()\ 
    .annotate(Count('photos'))\ 
    .filter(photos__is_public=True) 

大丈夫のようですが、: - クエリは奇妙 ある - 各ギャラリーに追加属性photos__countは、このギャラリーの写真の総数が含まれています、このギャラリーの公開写真の数ではなく、

私は私が必要とするハードコーディングされたSQLクエリがあることであることを薄い:

SELECT `gallery`.* , COUNT(`gallery_photos`.`photo_id`) 
FROM `gallery` 
    INNER JOIN `gallery_photos` ON (`gallery`.`id` = `gallery_photos`.`gallery_id`) 
    INNER JOIN `photo` ON (`gallery_photos`.`photo_id` = `photo`.`id`) 
WHERE `photo`.`is_public` = True 
GROUP BY gallery.id ; 

それを修正するために、任意のアイデア?

ありがとうございました! ;-)

答えて

0

Djangoのドキュメントは

http://docs.djangoproject.com/en/dev/topics/db/aggregation/#order-of-annotate-and-filter-clauses

にあり、私の経験では、次のクエリはと言う:

Gallery.objects.filter(photos__is_public=True).annotate(Count('photos')) 

がパブリックであり、少なくとも1枚の写真にあなたのギャラリーを与えるだろう公開されている写真のみの数。唯一のことは、パブリック写真がゼロのギャラリーを除外しますが、それについて気にしないように聞こえることです。上記のクエリをテストしましたか?

それでも正しいデータが返されない場合は、すべてが公開されているギャラリーだけが返されるため、返されたデータがアノテーションされている可能性があります。その場合、「余分な」方法を使用して、必要な数を得ることができます。

Gallery.objects.filter(photos__is_public=True).extra(select={ 
    "photo_count": """ 
    SELECT COUNT(`gallery_photos.id`) 
     FROM `gallery_photos` 
    WHERE `gallery_photos.gallery_id` `gallery.id AND 
     `gallery_photos.is_public = True 
    """}) 

Jason Christaの除外方法も使用できます。

+0

これはうまくいきます: '' Gallery.objects.filter(photos__is_public = True).annotate(Count( 'photos')) '' ありがとうございました。 –

0

は、これはそれを行う必要があります。

編集、カウント数を追加する更新:

SELECT `gallery`.*, 'a'.'count' 
FROM `gallery` 
inner join (
    select `gallery`.`id`, count(*) as count 
    from `gallery_photos` 
    INNER JOIN `photo` ON (`gallery_photos`.`photo_id` = `photo`.`id`) 
    where `photo`.`is_public` = True 
    group by `gallery`.`id` 
) a on `gallery`.`id` = 'a'.'id' 
WHERE `photo`.`is_public` = True 
+0

あなたのクエリは2つのSELECTと私のものを作ると思われます。だから私は私のクエリがより最適化されたと思う。 :p –

0

私がしようとするだろう:私はあなたは自分のフィルタを得たと考えている

Gallery.objects.filter(photos__is_public=True).annotate(Count('photos')) 

を間違って注文していますが、私はその仮定をテストするためにあなたのモデルを設定していません。

てみ番号2:

Gallery.objects.exclude(photos__is_public=False).annotate(Count('photos')) 

写真のどれもが公開されていないとされ、公開されていないものの数を返すすべてのギャラリーを除外しなければなりません。

+0

こんにちは、 * ALL *の写真が公開されているギャラリーを選択するため、これは機能しません。しかし、私は少なくとも*写真が公開されているギャラリーを選択する必要があります。さらに、あなたの '' phots__count''属性はすべての写真の数を含みます(公開と非公開)。 私も同じようにお手伝いしてくれてありがとうございます;-)! –

0

これは?

 
Gallery.objects.filter(photos__is_public=True)\ 
       .annotate(Count('photos__is_public')) 
+0

ハ、ジェイソンのquerysetは右と短い、IMOです。私はここでさらに多くのキーを入力したことを残念に思っています...]、今すぐスリープする必要があります...フィルタは結合された内部テーブルの行に適用されます。 – okm

関連する問題