2009-11-23 7 views
2

J'ai besoin de construire une requête dans Django, et je me demande si c'est en quelque sorte possible (cela peut être vraiment évident mais il me manque ...).Obtenir des lignes distinctes basées sur un certain champ d'une base de données dans Django

J'ai une requête normale Model.objects.filter(x=True)[:5] qui peut retourner des résultats comme celui-ci:

 
FirstName LastName Country 
Bob   Jones  UK 
Bill   Thompson  UK 
David   Smith  USA 

je dois les lignes d'appui seulement qui sont distinctes en fonction du champ Country, quelque chose comme Model.objects.filter(x=True).distinct('Country')[:5] serait idéal, mais ce n'est pas possible Django.

Les lignes que je veux la requête de saisir en fin de compte sont les suivants:.

 
FirstName LastName Country 
Bob   Jones  UK 
David   Smith  USA 

Je dois aussi la requête d'utiliser le même ordre tel que défini dans la classe Meta du modèle (par exemple je ne peux pas passer outre l'ordre dans en tous cas).

Comment ferais-je cela?

Merci beaucoup.

+0

J'ai seulement besoin des cinq premières rangées du DB. – Dx143

+0

C'est une question difficile, mais je ne suis pas sûr de bien comprendre la question. Voulez-vous les cinq premières lignes dans lesquelles le pays est distinct? – jathanism

+0

Salut - oui, je fais :). – Dx143

Répondre

0
countries = [f.country in Model.objects.all()] 

for c in countries: 
    try: 
     print Model.objects.filter(country=c) 
    except Model.DoesNotExist: 
     pass 
0

Je pense que @skrobul est sur la bonne voie, mais un peu plus loin.

Je ne pense pas que vous serez en mesure de le faire avec une seule requête, car la méthode distinct() ajoute le modificateur SELECT DISTINCT à la requête, qui agit sur la ligne entière. Vous devrez probablement créer une liste de pays, puis renvoyer des QuerySets limités en fonction de l'itération de cette liste.

Quelque chose comme ceci:

maxrows = 5 
countries = set([x.country for x in Model.objects.all()]) 
rows = [] 
count = 0 
for c in countries: 
    if count >= maxrows: 
     break 

    try: 
     rows.append(Model.objects.filter(country=c)[0]) 
    except Model.DoesNotExist: 
     pass 

    count += 1 

Ceci est un exemple très générique, mais il donne le résultat escompté.

4

Je ne l'ai pas testé, mais il me semble un dict devrait faire le travail, bien que la commande pourrait être hors tension puis:

d = {} 
for x in Model.objects.all(): 
    d[x.country] = x 

records_with_distinct_countries = d.values() 
+0

Cette même chose peut être effectuée en capturant les valeurs dans un 'set'. – jathanism

+1

Pas vraiment. Les pays peuvent être mis dans l'ensemble car ils sont immuables. Mais les modèles ne sont définitivement pas immuables, donc ne peuvent pas être dans un ensemble. C'est pourquoi j'utilise un dict, le pays immuable comme clé, et le record comme valeur. Il m'arrive d'utiliser les touches dict en tant qu'ensemble (ce qui est conceptuellement) sans perdre l'enregistrement. – extraneon

0

Pouvez-vous poster SQL brut qui renvoie ce que vous voulez de la base de données source? J'ai l'intuition que le problème réel ici est la structure de requête/données ...

Questions connexes