Django:分页ListView数据库性能

时间:2013-10-12 10:21:47

标签: database django django-generic-views django-pagination

我有ListView分页:

class StoriesListView(ListView):
    model = Story
    paginate_by = 20

    def get_queryset(self):
        return Story.objects.all().order_by('-updated_at')

我在数据库中有1000个Story个对象。当用户加载我的视图时会发生什么?是从数据库中查询所有1000还是只查询20?我该如何优化呢?

4 个答案:

答案 0 :(得分:5)

这取决于你如何使用它。 QuerySet对象是lazy,在这种特殊情况下,sql查询将添加LIMITOFFSET,因此查询将始终只返回20个结果。但是,当您希望在模板中使用相关对象时,必须使用select_relatedprefetch_related方法优化查询。

我认为你应该阅读django框架中optimize database access的方法。

希望这有帮助。

答案 1 :(得分:2)

Paginator类获取get_queryset的返回值(在这种情况下是整个查询集)并拼接它以使您只能访问20.它需要对整个查询集进行操作,否则你例如,将无法使用它来显示页面列表。

您可以看到关注代码以查看其实际效果:

get()> get_context_data()> paginate_queryset()> Paginator.init()

这意味着in your template contextqueryset变量是整个查询集。 page变量用于仅获取属于当前页面的那些对象。这是由splicing the initial queryset完成的,它将对其进行评估并点击数据库。您可以遍历该页面中的对象:{% for object in page %},这将不会再次访问数据库:

# https://github.com/django/django/blob/master/django/core/paginator.py#L119
def __getitem__(self, index):
    if not isinstance(index, (slice,) + six.integer_types):
        raise TypeError
    # The object_list is converted to a list so that if it was a QuerySet
    # it won't be a database hit per __getitem__.
    if not isinstance(self.object_list, list):
        self.object_list = list(self.object_list)
    return self.object_list[index]

答案 2 :(得分:0)

它只会获得20个物体。 Paginator将get_queryset方法的结果作为起始查询集,它只会在迭代时命中数据库,所以你很好。 get_queryset方法没有点击数据库本身。

答案 3 :(得分:-3)

我在分页期间遇到的同样问题。 对于分页,您不需要在模态中创建函数。

你可以使用LIMT,通过简单的我的通用功能可以做到这一点

def testPagination(请求):

dataObj             = paginationData('Item',page_no,10)
data["dataIndex"]   = dataObj["dataIndex"]
data["page_no"]     = dataObj["page_no"] #given page number will helps to active link at template
data["data"]        = dataObj["data"]  #actual data will helps in template
data['pagination']  = dataObj["pagination"] #Will helps to make dynamic link for pagination

广义分离功能

def paginationData(modalName,pageNo,perPage):
    data = {} #initialize variables
    Modal = getModel(modalName) # Function to get modal reference
    count = Modal.objects.count()#Calculate no of records
    no_of_record_per_page = ceil(float(count) / perPage)
    print ",Records counts : " + str(no_of_record_per_page)
    pages = [] #No of pages
    pages.append(1) 
    a = 1
    while a < (no_of_record_per_page):
        a += 1 # Same as a = a + 1
        pages.append(a)
    data["pagination"] = pages # pagenation for display link of page
    data["page_no"] = pageNo
    data['data'] = Modal.objects.all()[((pageNo-1)*perPage):(pageNo*perPage)]
    data['dataIndex'] = str((pageNo -1)*perPage) 
    return data