2014-01-09 82 views
0

這裏是我的模型:Django的複雜分組

class Location(models.Model): 
    city = models.CharField() 

class Competition(models.Model): 
    name = models.CharField() 
    location = models.ForeignKey(Location) 

class Laureate(models.Model): 
    name = models.CharField() 
    competitions = models.ManyToManyField(Competition, through='LaureateCompetition') 

class LaureateCompetition(models.Model): 
    laureate = models.ForeignKey(Laureate) 
    competition = models.ForeignKey(Competition) 

我使用PostgreSQL。 我基於Location試圖組Laureates

[ 
    { 
     "city": "Moscow", 
     "laureates" : ["Bob", "Peter", "Maria"] 
    }, 
    { 
     "city": "London", 
     "laureates" : ["Nicolai", "John", "Adam"] 
    } 
] 

我到底是什麼了做是看起來是這樣的:

SELECT app_location.country,  
    (SELECT array 
    (SELECT DISTINCT ON (app_laureate.name) app_laureate.name 
     FROM app_laureatecompetition 
     LEFT JOIN app_laureate ON app_laureate.id = app_laureatecompetition.laureate_id 
     WHERE app_laureatecompetition.competition_id IN 
      (SELECT app_competition.id 
      FROM app_competition 
      WHERE app_location.id = app_competition.location_id))) AS pupils 
FROM app_location 

我:

locations = [] 
all_laureate_competitions = LaureateCompetition.objects.select_related().all() 
all_competitions = Competition.objects.order_by('location')\ 
             .distinct('location')\ 
             .select_related() 

for competition in list(all_competitions): 
    location = competition.location 
    competitions = list(set(
     [x for x in all_laureate_competitions 
     if x.competition.location == location] 
    )) 
    laureates = list(set([x.name for x in competitions])) 
    locations.append(create_location(location, laureates)) 
return locations 

如果我用SQL做不太喜歡第一種方法。 做這樣的查詢有哪些常見的做法?我應該用原始的sql來做嗎?有更多的orm方式嗎?

+0

這可能有助於寫SQL在嘗試編寫匹配的Django ORM代碼之前。一旦你知道了SQL,你可能會想出如何讓ORM生成它。我養成這樣做的習慣。另外,它可能取決於你的數據庫。你基本上想從數據庫中取回數組。我知道PostgreSQL和psycopg2開箱即可,但我不知道其他數據庫。 – jpmc26

+0

@ jpmc26我在SQL中表達了它。請檢查編輯。 –

+0

我的意思是你想要的查詢,包括'GROUP BY'。如果你的數據庫不能返回一個數組,那麼你就像你一樣堅持用Python來做它。 – jpmc26

回答

0

你也許可以做這樣的事情:

results = [] 

for location in Location.objects.all(): 
    for competition in location.competition_set.all(): 
     for laurete_competition in competition.laurete_competition_set.all(): 
      results.append(laurete_competition.laurete_set.all()) 

print results 

另見外觀極好Django文檔,我經常去那裏時,我有一個類似的問題:
https://docs.djangoproject.com/en/dev/topics/db/models/#extra-fields-on-many-to-many-relationships