在`order_by`调用之后,Django Paginate中的重复元素

时间:2015-07-31 01:27:19

标签: django pagination django-rest-framework

我正在使用Django 1.7.7。

我想知道是否有人经历过这个。这是我的问题:

p = Paginator(events, 10)
p.count  # Gives 91

event_ids = []
for i in xrange(1, p.count / 10 + 2):
    event_ids += [i.id for i in p.page(i)]

print len(event_ids)  # Still 91
print len(set(event_ids))  # 75

当我尝试将其分页时

.order_by

我注意到如果删除了.order_by,我就不会重复了。然后我尝试使用Event.objects.all().order_by('date') events = Event.objects.filter( Q(date__gt=my_date) | Q(date__isnull=True) ).order_by('date') p = Paginator(events, 10) events.count() # Gives 131 p.count # Gives 131 event_ids = [] for i in xrange(1, p.count / 10 + 2): event_ids += [i.id for i in p.page(i)] len(event_ids) # Gives 131 len(set(event_ids)) # Gives 118 而没有重复。

最后,我尝试了这个:

object_list

......并且有重复。谁能解释一下发生了什么?

我挖掘了Django源代码(https://github.com/django/django/blob/master/django/core/paginator.py#L46-L55),这似乎与Django如何切割distinct()有关。

感谢任何帮助。感谢。

修改:[e for e in events.iterator()]对重复项没有影响。数据库中没有任何重复项,我认为查询不会引入任何重复项(In [1]: from django.core.paginator import Paginator In [2]: from datetime import datetime, timedelta In [3]: my_date = timezone.now() In [4]: 1 events = Event.objects.filter( 2 Q(date__gt=my_date) | Q(date__isnull=True) 3 ).order_by('date') In [5]: events.count() Out[5]: 134 In [6]: p = Paginator(events, 10) In [7]: p.count Out[7]: 134 In [8]: event_ids = [] In [9]: 1 for i in xrange(1, p.num_pages + 1): 2 event_ids += [j.id for j in p.page(i)] In [10]: len(event_ids) Out[10]: 134 In [11]: len(set(event_ids)) Out[11]: 115 不会产生任何重复项)。就在Paginator切片的时候。

Edit2:这是一个更完整的例子

removeFormat

2 个答案:

答案 0 :(得分:12)

哦,在黑暗中拍摄,但我想我可能知道它是什么。我无法在sqlite中重现它,但使用mysql。我认为mysql试图对具有相同值的列进行排序,它在切片期间返回相同的结果

分页拼接基本上是一个sql语句 SELECT ... FROM ... WHERE (date > D OR date IS NULL) ORDER BY date ASC LIMIT X OFFSET X

但是当date为null时我不确定mysql是如何对它进行排序的。因此,当我尝试LIMIT 10和LIMIT 10 OFFSET 10的两个sql查询时,它返回具有相同行的集合,而LIMIT 20生成一个唯一集合。

您可以尝试将order_by更新为 order_by('id','date'),让它首先按唯一字段排序,然后修复它。

答案 1 :(得分:0)

在将查询传递给.distinct()之前,尝试在查询中使用Paginator