2010-08-08 18 views
36

J'ai ce modèle:Obtenir des valeurs distinctes de queryset par le champ

class Visit(models.Model): 
    timestamp = models.DateTimeField(editable=False) 
    ip_address = models.IPAddressField(editable=False) 

Si un utilisateur visite plusieurs fois en une seule journée, comment puis-je filtrer les lignes uniques en fonction du champ ip? (Je veux que les visites uniques pour aujourd'hui)

today = datetime.datetime.today() 
yesterday = datetime.datetime.today() - datetime.timedelta(days=1) 

visits = Visit.objects.filter(timestamp__range=(yesterday, today)) #.something? 

EDIT:

Je vois que je peux utiliser:

Visit.objects.filter(timestamp__range=(yesterday, today)).values('ip_address') 

pour obtenir un ValuesQuerySet de juste les champs IP. Maintenant, mon QuerySet ressemble à ceci:

[{'ip_address': u'127.0.0.1'}, {'ip_address': u'127.0.0.1'}, {'ip_address': 
u'127.0.0.1'}, {'ip_address': u'127.0.0.1'}, {'ip_address': u'127.0.0.1'}] 

Comment filtrer cette unicité sans évaluer la QuerySet et en prenant le coup db?

# Hope it's something like this... 
values.distinct().count() 
+0

double possible de [Sélectionner des valeurs distinctes d'un champ de table] (http://stackoverflow.com/questions/2466496/select-distinct-values-from-a-table-field) –

Répondre

32

Qu'est-ce que vous voulez est:

Visit.objects.filter(stuff).values("ip_address").annotate(n=models.Count("pk")) 

Ce que cela fait est d'obtenir tous les ip_addresses puis il obtient le nombre de clés primaires (aka nombre de lignes) pour chaque adresse IP.

+2

Je ne pense pas que je comprenne totalement l'annotation. Comme vous l'avez écrit, mon ValuesQuerySet a maintenant "n": 1 ajouté à chaque entrée. Je ne suis pas sûr de ce que ça me dit? – Scott

+7

Le problème est probablement Meta.ordering - essayez ceci 'Visit.objects.filter (stuff) .order_by(). Values ​​(" ip_address "). Annoter (n = models.Count (" pk "))' – Greg

+1

@Greg Merci toi! Je nouveau que les 'ordering' et' order_by() 'cause des problèmes avec' distinct' mais je ne savais pas comment le résoudre - bien qu'il se trouve dans les documents de l'API QuerySet sous ['order_by()'] (https://docs.djangoproject.com/fr/dev/ref/models/querysets/# order-by) "_Si vous ne voulez pas qu'un ordre soit appliqué à une requête, pas même l'ordre par défaut, appelez 'order_by()' sans paramètre._ " –

13

Avec Alex Réponse J'ai aussi le n: 1 pour chaque article. Même avec une clause distinct().

C'est bizarre parce que c'est de retour les bons numéros d'articles:

Visit.objects.filter(stuff).values("ip_address").distinct().count() 

Mais quand j'itérer sur "Visit.objects.filter (choses) .values ​​(" ip_address "). Distincte()" I a obtenu beaucoup plus d'articles et des doublons ...

EDIT:

La clause de filtre me causait des problèmes. Je filtrais avec un autre champ de table et un SQL JOIN a été fait qui brisait les choses distinctes. J'ai utilisé cette astuce pour voir la requête qui a été vraiment utilisé:

q=Visit.objects.filter(myothertable__field=x).values("ip_address").distinct().count() 
print q.query 

Je la classe est ensuite revenu sur la sorcière que je faisais la requête et le filtre d'avoir une jointure qui ne repose pas sur une « visite » id.

espérons que cette aide

+0

Est-ce une question ou une réponse? – User

+0

c'était une sorte de complément à la réponse d'Alex. J'ai essayé, j'ai eu le même problème que vfxcode, et puis j'ai trouvé pourquoi. Alors j'ai pensé que je devais partager mes découvertes. 3 ans plus tard, j'avoue que ma réponse était un peu brouillon et je comprends pourquoi tu demandes ça;) –