vag*_*ond 65 django pagination
我在Django中使用分页时遇到问题.以下面的URL为例:
http://127.0.0.1:8000/users/?sort=first_name
Run Code Online (Sandbox Code Playgroud)
在此页面上,我按其first_name对用户列表进行排序.没有排序GET变量,它默认按id排序.
现在,如果我点击下一个链接,我希望以下网址:
http://127.0.0.1:8000/users/?sort=first_name&page=2
Run Code Online (Sandbox Code Playgroud)
相反,我失去了所有得到的变量,最终得到了
http://127.0.0.1:8000/users/?page=2
Run Code Online (Sandbox Code Playgroud)
这是一个问题,因为第二页按id而不是first_name排序.
如果我使用request.get_full_path,我最终会得到一个丑陋的URL:
http://127.0.0.1:8000/users/?sort=first_name&page=2&page=3&page=4
Run Code Online (Sandbox Code Playgroud)
解决办法是什么?有没有办法访问模板上的GET变量并替换页面的值?
我正在使用Django文档中描述的分页,我的偏好是继续使用它.我使用的模板代码与此类似:
{% if contacts.has_next %}
<a href="?page={{ contacts.next_page_number }}">next</a>
{% endif %}
Run Code Online (Sandbox Code Playgroud)
mpa*_*paf 55
我认为提出的自定义标签过于复杂,这就是我在模板中所做的:
<a href="?{% url_replace request 'page' paginator.next_page_number %}">
Run Code Online (Sandbox Code Playgroud)
标签功能:
@register.simple_tag
def url_replace(request, field, value):
dict_ = request.GET.copy()
dict_[field] = value
return dict_.urlencode()
Run Code Online (Sandbox Code Playgroud)
如果url_param尚未包含在url中,则会添加值.如果它已经存在,它将被新值替换.这是一个适合我的简单解决方案,但是当url具有多个具有相同名称的参数时不起作用.
您还需要从视图中将RequestContext请求实例提供给模板.更多信息:
http://lincolnloop.com/blog/2008/may/10/getting-requestcontext-your-templates/
sko*_*l00 36
我认为url_replace解决方案可以更优雅地重写
from urllib.parse import urlencode
from django import template
register = template.Library()
@register.simple_tag(takes_context=True)
def url_replace(context, **kwargs):
query = context['request'].GET.copy()
query.update(kwargs)
return query.urlencode()
Run Code Online (Sandbox Code Playgroud)
模板字符串简化为
<a href="?{% url_replace page=paginator.next_page_number %}">
Run Code Online (Sandbox Code Playgroud)
这允许替换多个键但不允许使用重复键进行查询.
vag*_*ond 12
经过一番游戏,我找到了一个解决方案......虽然我不知道它是不是真的很好.我更喜欢更优雅的解决方案.
无论如何,我将请求传递给模板,并能够通过request.GET访问所有GET变量.然后我遍历GET字典,只要变量不是页面我就打印它.
{% if contacts.has_previous %}
<a href="?page={{ contacts.previous_page_number }}{% for key,value in request.GET.items %}{% ifnotequal key 'page' %}&{{ key }}={{ value }}{% endifnotequal %}{% endfor %}">previous</a>
{% endif %}
<span class="current">
Page {{ contacts.number }} of {{ contacts.paginator.num_pages }}.
</span>
{# I have all of this in one line in my code (like in the previous section), but I'm putting spaces here for readability. #}
{% if contacts.has_next %}
<a href="?page={{ contacts.next_page_number }}
{% for key,value in request.GET.items %}
{% ifnotequal key 'page' %}
&{{ key }}={{ value }}
{% endifnotequal %}
{% endfor %}
">next</a>
{% endif %}
Run Code Online (Sandbox Code Playgroud)
在你的views.py身上,你会以某种方式访问你排序的标准,例如first_name.您需要将该值传递给模板并将其插入其中以记住它.
例:
{% if contacts.has_next %}
<a href="?sort={{ criteria }}&page={{ contacts.next_page_number }}">next</a>
{% endif %}
Run Code Online (Sandbox Code Playgroud)
可以创建一个上下文处理器以在任何应用分页的地方使用它。
例如,在my_project/my_app/context_processors.py:
def getvars(request):
"""
Builds a GET variables string to be uses in template links like pagination
when persistence of the GET vars is needed.
"""
variables = request.GET.copy()
if 'page' in variables:
del variables['page']
return {'getvars': '&{0}'.format(variables.urlencode())}
Run Code Online (Sandbox Code Playgroud)
将上下文处理器添加到 Django 项目设置中:
TEMPLATE_CONTEXT_PROCESSORS = (
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'django.core.context_processors.i18n',
'django.core.context_processors.request',
'django.core.context_processors.media',
'django.core.context_processors.static',
...
'my_project.my_app.context_processors.getvars',
)
Run Code Online (Sandbox Code Playgroud)
然后,在您的模板中,您可以在分页时使用它:
<div class="row">
{# Initial/backward buttons #}
<div class="col-xs-4 col-md-4 text-left">
<a href="?page=1{{ getvars }}" class="btn btn-rounded">{% trans 'first' %}</a>
{% if page_obj.has_previous %}
<a href="?page={{ page_obj.previous_page_number }}{{ getvars }}" class="btn btn-rounded">{% trans 'previous' %}</a>
{% endif %}
</div>
{# Page selection by number #}
<div class="col-xs-4 col-md-4 text-center content-pagination">
{% for page in page_obj.paginator.page_range %}
{% ifequal page page_obj.number %}
<a class="active">{{ page }}</a>
{% else %}
<a href="?page={{ page }}{{ getvars }}">{{ page }}</a>
{% endifequal %}
{% endfor %}
</div>
{# Final/forward buttons #}
<div class="col-xs-4 col-md-4 text-right">
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}{{ getvars }}" class="btn btn-rounded">{% trans 'next' %}</a>
{% endif %}
<a href="?page={{ paginator.num_pages }}{{ getvars }}" class="btn btn-rounded">{% trans 'last' %}</a>
</div>
</div>
Run Code Online (Sandbox Code Playgroud)
无论您在请求中使用什么 GET 变量,它们都将附加在?page=GET 参数之后。
改善这种方式:
使用urlencodefromdjango而不是urllib, 以防止参数UnicodeEncodeError错误unicode。
模板标签:
from django.utils.http import urlencode
@register.simple_tag(takes_context=True)
def url_replace(context, **kwargs):
query = context['request'].GET.dict()
query.update(kwargs)
return urlencode(query)
Run Code Online (Sandbox Code Playgroud)
模板:
<!-- Pagination -->
<div class="pagination">
<span class="step-links">
{% if coupons.has_previous %}
<a href="?{% url_replace page=objects.previous_page_number %}">Prev</a>
{% endif %}
<span class="current">
Page {{ objects.number }} of {{ objects.paginator.num_pages }}
</span>
{% if objects.has_next %}
<a href="?{% url_replace page=objects.next_page_number %}">Next</a>
{% endif %}
</span>
</div>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
23697 次 |
| 最近记录: |