2017-01-31 4 views
0

リストクエリでは、特定のサイトの特定の製品にいくつの価格が存在するかを示したいとします。Django ORM:rawsqlを使用しないでCount()(サブクエリ)でアノテーションをフィルタする方法

私はこれまでRawSQLを使ってこれを行う方法を見つけました。私は何か見落としていますか?

class Site(Model): 
    name = models.CharField(_('display name'), max_length=50) 


class Price(Model): 
    name = models.CharField() 


class SitePrice(Model): 
    price = models.ForeignKey(Price) 
    site = models.ForeignKey(Site) 

今、私が欲しいの表は、次のとおりです:

queryset = Price.objects.all() 
    site_annotations = {} 
    for site in Site.objects.all(): 
     site_annotations['num_prices_{}'.format(site.name)] = RawSQL(
      'SELECT COUNT(id) ' 
      'FROM `product_siteprice` ' 
      'WHERE `product_siteprice`.`price_id` = `product_price`.`id` ' 
      'AND site_id=%s', [site.pk] 
     ) 

    queryset = queryset.annotate(**site_annotations) 

編集

私のモデルは次のように簡略化されて見え

Product | Nr of prices on Site A | Nr of prices on Site B | 
--------|------------------------|------------------------| 
Iphone | 6      | 3      | 
Xperia | 42      | 66      | 

そして私は、並べ替え、フィルタ処理したいです価格の数、なぜ私は注釈が必要なのですか。あなたはコンテキストの残りの部分がわからない場合

NB名前価格は、この文脈では、それはより多くの製品のように見ることができ、少し誤解を招くおそれがあり私が理解、あなただけの価格をフィルタリングする必要があるから

+1

私の答えが間違っている場合は、モデルの関連部分を含めていただけますか? – Sayse

+0

私は何をしたいかについてより多くの文脈を追加しました –

+0

Iveが私の答えを更新しました – Sayse

答えて

0

関連サイトで、オブジェクト数のカウントを取得します。

Price.objects.filter(site_price__site_id=site.pk).count() 

あなただけのサイトの価格モデルを削除し、多くの分野に多くのと交換したい場合がありますが

0

私はあなたが欲しいクエリはこのようなものに見えると思います:

qs = SitePrice.objects.values('price_id', 'site_id').annotate(d_count=Count('id')) 

そして、あなたが望むテーブルを得るには、次のようなものを使ってdictにフォーマットします:

from collections import defaultdict 
values = defaultdict(dict) 
for x in qs: 
    values[ x['price_id'] ][ x['site_id'] ] = x['d_count'] 

この表をプリントアウトするには、あなたが使用します。

price_ids = list(values.keys()) # you don’t need `list` for python 2 
site_ids = set() 
for x in values.values(): 
    site_ids |= set(x.keys()) 
site_ids = list(site_ids) 
site_ids.sort() 
prices = dict(Price.objects.filter(id__in=price_ids).values_list('id', 'name')) 
sites = dict(Site.objects.filter(id__in=site_ids).values_list('id', 'name')) 
print('   ', end='') # for python 3 
# print '  ', # for python 2 
for x in site_ids: 
    print('%-8s ' % sites[x], end='') 
print('') 
for x, counts in values.items(): 
    print('%-8s ' % prices[x], end='') 
    for site_id in site_ids: 
     d_count = counts.get(site_id, 0) 
     print('%-8s ' % d_count, end='') 
    print('') 
関連する問題