2011-05-04 64 views
21

删除重复有一个简单的方法,以消除在下列基本查询重复 -在Django查询

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

我试图用重复的(),但它不工作。你能否告诉我没有重复做这个查询的确切语法?谢谢。

+2

当多行处理,请参阅:http://stackoverflow.com/questions/13700200/django-remove-duplicate-objects-where-there - 多于一个字段的比较/ 13700642#13700642 – 2014-01-14 12:12:03

回答

64

这个查询不会给你重复 - 即它会给你数据库中的所有行,通过电子邮件排序。

但是,我认为你的意思是你的数据库中有重复的数据。在这里添加distinct()不会有帮助,因为即使您只有一个字段,也会自动创建一个id字段 - 因此,id + email的组合不是唯一的。

假设你只需要一个字段,email_address,消除重复的,你可以这样做:

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

但是,你真的应该解决的根本问题,并从数据库中删除重复的数据。

例如,删除通过电子邮件字段重复的电子邮件:按名称

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() 

或书籍:

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() 
+0

伟大的解决方案。当使用'.values(..)'时,你甚至可以将它作为kwargs传递给'.filter(...)' – vdboor 2014-04-29 14:39:10

+0

在第二个代码示例中,我们应该设置varagable以删除电子邮件的所有重复项?一旦迭代完成,Email.objects成为Email对象的整个查询集合,不是吗? – nextdoordoc 2016-07-21 10:40:06

3

您可能可以使用distinct()功能,具体取决于您的型号。如果你只想检索单场形成的模型,你可以这样做:

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

这应该给你的电子邮件的有序列表。

0

我用下面的实际从数据库中删除重复的条目,希望这可以帮助其他人。

adds = Address.objects.all() 
d = adds.distinct('latitude', 'longitude') 
for address in adds:  
    if i not in d: 
    address.delete() 
+1

围绕ORM操作实现循环通常是一个坏主意,因为它不能很好地扩展。在这个例子中,你有很多很多的查询正在执行。假设'adds'中有很多行返回。在每个循环中,您都会启动第一个查询来查看“我不在d”中,可能还有另一个用于删除受影响的“地址”记录。你可以直接在ORM中执行这个操作,而不需要Python循环:'Address.objects.exclude(pk__in = d.values('pk,flat = True))。delete()'。 (您可能需要调整 - 我没有测试过)。 – BillyBBone 2015-02-26 23:33:02

+0

感谢您的提示 – 2015-02-27 07:47:40

2

对于检查重复,你可以做Django为低于GROUP_BYHAVING。我们在这里使用Django annotations

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) 

现在通过上述数据循环并删除所有其他emails除了第一个(取决于要求或其他)。

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

您还可以使用set()

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