我正试图与django分页系统联系并得到一个低级别的问题。
我一直在挖掘Manager,Queryset和Paginator的代码,但我无法找到Paginator
所在的地方{{3}在SQL查询上设置限制和偏移量,强制它只返回查询集的一部分。
以下是由paginator生成的SQL示例:
>>> from django.db import connection
>>>
>>> paginator = Paginator(Myobject.objects.filter(foreign_key='URS0000416056'), 1)
>>> for myobject in paginator.page(1):
>>> print myobject
Myobject object
>>>
>>> print connection.queries
[{u'time': u'0.903', u'sql': u'SELECT COUNT(*) AS "__count" FROM "xref" WHERE "xref"."upi" = \'URS0000416056\''}, {u'time': u'0.144', u'sql': u'SELECT "xref"."id", "xref"."dbid", "xref"."ac", "xref"."created", "xref"."last", "xref"."upi", "xref"."version_i", "xref"."deleted", "xref"."timestamp", "xref"."userstamp", "xref"."version", "xref"."taxid" FROM "xref" WHERE "xref"."upi" = \'URS0000416056\' LIMIT 1 OFFSET 1'}]
答案 0 :(得分:2)
感谢链接到源代码,他们让我挖掘细节。
在构造Paginator
个实例时, Page
在包装的查询集上使用切片表示法:
return self._get_page(self.object_list[bottom:top], number, self)
https://github.com/django/django/blob/master/django/core/paginator.py#L57
此处object_list
是一个查询集,尽管名称如果您首先在查询集上使用了Paginator
。
反过来,查询集在__getitem__
方法中实现切片表示法:
qs.query.set_limits(start, stop)
切片特定处理当前从https://github.com/django/django/blob/master/django/db/models/query.py#L260开始。
查询类使用set_limits
方法将查询类转换为查询的低位和高位属性:
def set_limits(self, low=None, high=None):
"""
Adjust the limits on the rows retrieved. Use low/high to set these,
as it makes it more Pythonic to read and write. When the SQL query is
created, convert them to the appropriate offset and limit values.
Apply any limits passed in here to the existing constraints. Add low
to the current low value and clamp both to any existing high value.
"""
if high is not None:
if self.high_mark is not None:
self.high_mark = min(self.high_mark, self.low_mark + high)
else:
self.high_mark = self.low_mark + high
if low is not None:
if self.high_mark is not None:
self.low_mark = min(self.high_mark, self.low_mark + low)
else:
self.low_mark = self.low_mark + low
if self.low_mark == self.high_mark:
self.set_empty()
(截至2017年9月的当前实施情况,未来可能会发生变化。)
低标记和高标记反过来转变为SQLCompiler
as_sql
方法中的LIMIT和OFFSET查询参数:
if with_limits:
if self.query.high_mark is not None:
result.append('LIMIT %d' % (self.query.high_mark - self.query.low_mark))
if self.query.low_mark:
if self.query.high_mark is None:
val = self.connection.ops.no_limit_value()
if val:
result.append('LIMIT %d' % val)
result.append('OFFSET %d' % self.query.low_mark)