Sil*_*ght 11 python sql django pagination
我在我的网站上到处都使用Django Paginator,甚至还写了一个特殊的模板标签,以使它更方便.但现在我进入了一个状态,我需要在其中创建一个复杂的自定义原始SQL查询,没有LIMIT将返回大约100K记录.
如何在自定义查询中使用Django Pagintor?
我的问题的简化示例:
我的模特:
class PersonManager(models.Manager):
def complicated_list(self):
from django.db import connection
#Real query is much more complex
cursor.execute("""SELECT * FROM `myapp_person`""");
result_list = []
for row in cursor.fetchall():
result_list.append(row[0]);
return result_list
class Person(models.Model):
name = models.CharField(max_length=255);
surname = models.CharField(max_length=255);
age = models.IntegerField();
objects = PersonManager();
Run Code Online (Sandbox Code Playgroud)
我在Django ORM中使用pagintation的方式:
all_objects = Person.objects.all();
paginator = Paginator(all_objects, 10);
try:
page = int(request.GET.get('page', '1'))
except ValueError:
page = 1
try:
persons = paginator.page(page)
except (EmptyPage, InvalidPage):
persons = paginator.page(paginator.num_pages)
Run Code Online (Sandbox Code Playgroud)
这样,Django变得非常聪明,并LIMIT在执行时添加查询.但是当我使用自定义管理器时:
all_objects = Person.objects.complicated_list();
Run Code Online (Sandbox Code Playgroud)
选择所有数据,然后切片python列表,这非常慢.如何使我的自定义管理器的行为类似于内置管理器?
特别是看看Paginator的源代码,page()函数,我认为只需要实现切片,并将其转换为SQL查询中的相关LIMIT子句.您可能还需要添加一些缓存,但这看起来像QuerySet,所以也许您可以做其他事情:
(为了您的信息 - 我已经使用这种方法很长一段时间了,即使与VIEW伪造m2m中间表的复杂的多对多关系.)
这是RawPaginator我制作的一个类,它覆盖了Paginator原始查询。它需要一个附加参数,count即查询的总数。它不会对 进行切片,因为您必须通过和object_list在原始查询中分页。OFFSETLIMIT
from django.core.paginator import Paginator
class RawPaginator(Paginator):
def __init__(self, object_list, per_page, count, **kwargs):
super().__init__(object_list, per_page, **kwargs)
self.raw_count = count
def _get_count(self):
return self.raw_count
count = property(_get_count)
def page(self, number):
number = self.validate_number(number)
return self._get_page(self.object_list, number, self)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6606 次 |
| 最近记录: |