web-dev-qa-db-fra.com

Obtenez des valeurs distinctes de Queryset par champ

J'ai ce modèle:

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

Si un utilisateur visite plusieurs fois en une journée, comment puis-je filtrer les lignes uniques en fonction du champ ip? (I veulent 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?

MODIFIER:

Je vois que je peux utiliser:

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

pour obtenir un ValuesQuerySet contenant uniquement 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 puis-je filtrer ceci pour l'unicité sans évaluer le QuerySet et prendre le hit db?

# Hope it's something like this...
values.distinct().count()
46
Scott

Ce que vous voulez c'est:

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

Ce que cela fait, c'est obtenir toutes les adresses IP, puis il obtient le nombre de clés primaires (alias nombre de lignes) pour chaque adresse IP.

38
Alex Gaynor

Avec Alex Answer, j'ai également le n: 1 pour chaque élément. Même avec une clause distinct ().

C'est bizarre car cela renvoie le bon nombre d'articles:

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

Mais quand j'itère sur "Visit.objects.filter (stuff) .values ​​(" ip_address "). Distinct ()" J'ai obtenu beaucoup plus d'articles et quelques doublons ...

MODIFIER:

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

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

J'ai ensuite rétabli la classe sur laquelle je faisais la requête et le filtre pour avoir une jointure qui ne repose sur aucun identifiant "Visit".

j'espère que cela t'aides

17
Guillaume Gendre