Django分页开销与排序 [英] Django pagination overhead with sorting

查看:222
本文介绍了Django分页开销与排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试使用某些排序方式在Django中实现分页结构,但我无法确定如何正确执行。



视图。 py

  def search(request):
eList = Employer.objects.filter(eminence__lt = 4 ).order_by(' - eminence')

paginator = Paginator(eList,3)#显示每页3个联系人

page = request.GET.get('page' )
try:
employerList = paginator.page(page)
除了PageNotAnInteger:
employerList = paginator.page(1)
除了EmptyPage:
employerList = paginator.page(paginator.num_pages)

返回render_response(请求,雇主/ search.html,{'雇主列表':雇主列表})
/ pre>

search.html

 < div class =pagination> 
< span class =step-links>
{%如果employerList.has_previous%}
< a href =?page = {{employerList.previous_page_number}}> previous< / a>
{%endif%}

< span class =current> {{employerList.paginator.num_pages}}的页面{{employerList.number}}。< / span>
{%如果employerList.has_next%}
< a href =?page = {{employerList.next_page_number}}> next< / a>
{%endif%}
< / span>
< / div>

这个例子很好,但是你可以看到,对于每个导航,我需要得到所有的雇主对象。之后, Paginator 根据页码处理查询中的对象。但是,我认为分页应该在查询期间完成,只有根据页码才能得到我想要的X对象。当然,我可以修改代码,但是我不明白为什么人们使用 Paginator 虽然有这样的开销。我可能会忽略一个细节...



我的第二个问题是如何应用排序我的列表?我应该修改我的 url 并传递排序方法和页码,并根据他们通过sort方法得到quesy,并将其赋予 Paginator



这似乎是合理和罚款,但我只是想知道有没有更好的做法在django。



谢谢

解决方案

Django对于延迟加载数据非常聪明,这使得这些查询非常有效。我们来看看你的请求会发生什么...

  eList = Employer.objects.filter(eminence__lt = 4).order_by '-eminence')
##没有数据库查询。

paginator = Paginator(eList,3)
##没有数据库查询。

employerList = paginator.page(2)
## SELECT COUNT(*)FROM`yourproject_employer`
## WHERE`yourproject_employer`.`eminence`< 4

#强制迭代。与循环结果相同:
foo = list(employerList.object_list)
## SELECT * FROM`yourproject_employer`
## WHERE`yourproject_employer`.`eminence`< 4
## ORDER BY`yourproject_employer`.`eminence` DESC
## LIMIT 3 OFFSET 3

至于你的排序问题,我会说你只是按照你的建议修改 GET 参数。只要将非常小心地传递给数据库。例如,我会列出可能的排序并对此进行验证。这也意味着您不必公开数据库的内部工作。

  VALID_SORTS = {
pk:pk,
pkd:-pk,
em:eminence,
emd:-eminence,
}
DEFAULT_SORT ='pk'
def search(request):
sort_key = request.GET.get('sort',DEFAULT_SORT)#将pk替换为默认值。
sort = VALID_SORTS.get(sort_key,DEFAULT_SORT)

eList = Employer.objects.filter(eminence__lt = 4).order_by(sort)


I try to implement pagination structure in Django with some sort options however, I can't figure out how can I do that properly.

views.py

def search(request):
    eList = Employer.objects.filter(eminence__lt=4).order_by('-eminence')

    paginator = Paginator(eList, 3) # Show 3 contacts per page

    page = request.GET.get('page')
    try:
        employerList = paginator.page(page)
    except PageNotAnInteger:
        employerList = paginator.page(1)
    except EmptyPage:
        employerList = paginator.page(paginator.num_pages)

return render_response(request, 'employer/search.html', {'employerList':employerList})

search.html

<div class="pagination">
    <span class="step-links">
        {% if employerList.has_previous %}
            <a href="?page={{ employerList.previous_page_number }}">previous</a>
        {% endif %}

        <span class="current"> Page {{ employerList.number }} of {{ employerList.paginator.num_pages }}.</span>
        {% if employerList.has_next %}
            <a href="?page={{ employerList.next_page_number }}">next</a>
        {% endif %}
    </span>
</div>

This example works great however as you can see, for every navigation I need to get all Employer objects. After that Paginator handles the objects in query depending on page number. However, I think the pagination should be done during query and only get X objects that I want depending on page number. I can modify, of course, the code in that manner but I can't figure out why people use Paginator although there is such overhead. I may overlook a detail...

My second question is how can I apply sort my list ? Should I modify my url and passing a sort method and page number, and depending on them get the quesy by sort method and give it to Paginator ?

This seems reasonable and fine by me but I just wonder is there any better approach to do in django.

Thanks

解决方案

Django is very smart about lazy-loading the data, which makes these queries very efficient. Let's walk through what happens with your requests...

eList = Employer.objects.filter(eminence__lt=4).order_by('-eminence')
## No database query.

paginator = Paginator(eList, 3)
## No database query.

employerList = paginator.page(2)
## SELECT COUNT(*) FROM `yourproject_employer`
## WHERE `yourproject_employer`.`eminence` < 4

 # Force iteration.  Same as looping over results:
foo = list(employerList.object_list)
## SELECT * FROM `yourproject_employer`
## WHERE `yourproject_employer`.`eminence` < 4
## ORDER BY `yourproject_employer`.`eminence` DESC
## LIMIT 3 OFFSET 3

As for your sorting question, I would say to simply modify the GET arguments as you suggested. Just be very careful passing this to the database. I would, for example, make a list of possible sorts and verify against that. This also means you don't have to expose the inner-workings of your database.

VALID_SORTS = {
    "pk": "pk",
    "pkd": "-pk",
    "em": "eminence",
    "emd": "-eminence",
}
DEFAULT_SORT = 'pk'
def search(request):
    sort_key = request.GET.get('sort', DEFAULT_SORT) # Replace pk with your default.
    sort = VALID_SORTS.get(sort_key, DEFAULT_SORT)

    eList = Employer.objects.filter(eminence__lt=4).order_by(sort)

这篇关于Django分页开销与排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆