53 votes

Suppression des doublons dans une requête Django

Existe-t-il un moyen simple de supprimer les doublons dans la requête de base suivante :

email_list = Emails.objects.order_by('email')

J'ai essayé d'utiliser duplicate() mais cela ne fonctionnait pas. Quelle est la syntaxe exacte pour effectuer cette requête sans doublons ?

3 votes

Lorsqu'il s'agit de rangs multiples, veuillez consulter : stackoverflow.com/questions/13700200/

0 votes

Ce site c'est répondre en résolvant ce qui a été demandé, avec soi-même groupe par en retournant QuerySet.

136voto

Daniel Roseman Points 199743

Cette requête ne vous donnera pas de doublons - c'est-à-dire qu'elle vous donnera toutes les lignes de la base de données, classées par email.

Cependant, je suppose que vous voulez dire que vous avez des données en double dans votre base de données. Ajout de distinct() ici ne sera pas utile, car même si vous n'avez qu'un seul champ, vous avez aussi un champ automatique id La combinaison id+email n'est donc pas unique.

En supposant que vous n'ayez besoin que d'un seul champ, email_address dédupliqués, vous pouvez le faire :

email_list = Email.objects.values_list('email', flat=True).distinct()

Cependant, vous devez vraiment résoudre le problème de base et supprimer les données en double de votre base de données.

Exemple, suppression des doublons d'e-mails par champ d'e-mail :

for email in Email.objects.values_list('email', flat=True).distinct():
    Email.objects.filter(pk__in=Email.objects.filter(email=email).values_list('id', flat=True)[1:]).delete()

Ou des livres par nom :

for name in Book.objects.values_list('name', flat=True).distinct(): 
    Book.objects.filter(pk__in=Artwork.objects.filter(name=name).values_list('id', flat=True)[3:]).delete()

18voto

Parag Tyagi Points 2511

Pour vérifier le duplicata, vous pouvez faire un GROUP_BY y HAVING en Django comme ci-dessous. Nous utilisons Django annotations aquí.

from django.db.models import Count
from app.models import Email

duplicate_emails = Email.objects.values('email').annotate(email_count=Count('email')).filter(email_count__gt=1)

Maintenant, en bouclant à travers les données ci-dessus et en supprimant tous les autres emails à l'exception de la première (cela dépend de l'exigence ou autre).

for data in duplicates_emails:
    email = data['email']
    Email.objects.filter(email=email).order_by('pk')[1:].delete()

12voto

zeekay Points 22640

Vous pouvez enchaîner .distinct() à la fin de votre queryset pour filtrer les doublons. Consultez le site : http://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.distinct

2 votes

Vous n'avez pas compris la question.

7voto

Vous pouvez utiliser le distinct() en fonction de votre modèle. Si vous ne voulez récupérer qu'un seul champ du modèle, vous pouvez faire quelque chose comme.. :

email_list = Emails.objects.values_list('email').order_by('email').distinct()

ce qui devrait vous donner une liste ordonnée d'emails.

2voto

Trying2Learn Points 11

Vous pouvez également utiliser set()

email_list = set(Emails.objects.values_list('email', flat=True))

0 votes

J'essayais de supprimer les doublons après avoir créé une union de deux querysets. J'ai essayé d'utiliser la méthode distincte et de mettre all à false qs_1.union(qs_2, all=False). Je n'ai pas réussi à faire fonctionner les méthodes ci-dessus et j'ai donc utilisé set.

0 votes

Note d'avertissement : j'ai eu ce problème et set() a fonctionné pour supprimer l'enregistrement dupliqué, mais il semble casser le order_by (que je l'applique avant ou après).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X