Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用其他get变量对Django进行分页?_Django_Pagination - Fatal编程技术网

如何使用其他get变量对Django进行分页?

如何使用其他get变量对Django进行分页?,django,pagination,Django,Pagination,我在中使用分页时遇到问题。以下面的URL为例: http://127.0.0.1:8000/users/?sort=first_name 在这个页面上,我按照用户的名字对用户列表进行排序。如果没有sort GET变量,它默认为按id排序 现在,如果单击下一个链接,我希望看到以下URL: http://127.0.0.1:8000/users/?sort=first_name&page=2 相反,我丢失了所有get变量,并以 http://127.0.0.1:8000/users/?p

我在中使用分页时遇到问题。以下面的URL为例:

http://127.0.0.1:8000/users/?sort=first_name
在这个页面上,我按照用户的名字对用户列表进行排序。如果没有sort GET变量,它默认为按id排序

现在,如果单击下一个链接,我希望看到以下URL:

http://127.0.0.1:8000/users/?sort=first_name&page=2
相反,我丢失了所有get变量,并以

http://127.0.0.1:8000/users/?page=2
这是一个问题,因为第二页是按id排序的,而不是按名字排序的

如果我使用request.get_full_路径,我最终会得到一个丑陋的URL:

http://127.0.0.1:8000/users/?sort=first_name&page=2&page=3&page=4
解决办法是什么?是否有方法访问模板上的GET变量并替换页面的值

我正在使用中描述的分页,我的首选是继续使用它。我使用的模板代码与此类似:

{% if contacts.has_next %}
    <a href="?page={{ contacts.next_page_number }}">next</a>
{% endif %}
{%if contacts.has_next%}
{%endif%}

在您的
视图.py
中,您将以某种方式访问排序所依据的标准,例如
名字
。您需要将该值传递给模板并将其插入其中以记住它

例如:

{% if contacts.has_next %}
    <a href="?sort={{ criteria }}&page={{ contacts.next_page_number }}">next</a>
{% endif %}
{%if contacts.has_next%}
{%endif%}

玩了一会儿之后,我找到了一个解决方案。。。虽然我不知道它是否真的好。我想要一个更优雅的解决方案

无论如何,我将请求传递给模板,并且能够通过request.GET访问所有GET变量。然后我循环使用GET字典,只要变量不是page,我就打印它

{% 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 %}
{%if contacts.has_previous%}
{%endif%}
第{{contacts.paginator.num_pages}页中的第{{contacts.number}页。
{#我在代码中把所有这些都放在一行中(就像上一节一样),但是为了可读性,我在这里放了空格
{%if contacts.has_next%}
{%endif%}

您在视图中放置的每个此类链接都必须配备相关参数。没有可以转换的隐含魔法:

进入:

因此,您需要的是一些
Sorter
object/class/function/snippet(任何适合这里的东西都不会过度),它的作用类似于django.core.paginator.paginator,但会处理
sort
GET参数

可以这么简单:

sort_order = request.GET.get('sort', 'default-criteria')

<paginate, sort>

return render_to_response('view.html', {
    'paginated_contacts': paginated_contacts,  # Paginator stuff
    'sort_order': sort_order if sort_oder != 'default-criteria' else ''
})
sort\u order=request.GET.GET('sort','default criteria')
返回render\u to\u响应('view.html'{
“分页的_联系人”:分页的_联系人,#分页器内容
“排序顺序”:如果排序顺序!=“默认条件”否则“排序顺序”
})
那么,在你看来:

{% if contacts.has_next %}
    <a href="?page={{ contacts.next_page_number }}{%if sort_order%}&sort={{sort_oder}}{%endif%}">next</a>
{% endif %}
{%if contacts.has_next%}
{%endif%}

我可以变得更通用,但我希望您能理解这个概念。

'path':request.get_full_path().rsplit('&page')[0],

这里有一个用于构造查询字符串的有用的自定义模板标记

<a href="?{% make_query_string page=obj_list.next_page_number %}">Next page</a>

我认为建议的自定义标记太复杂,这是我在模板中所做的:

<a href="?{% url_replace request 'page' paginator.next_page_number %}">
href="?page={{ objects.next_page_number }}&{{path}}"
如果url_参数尚不在url中,则会添加值。如果它已经存在,则将被新值替换。这是一个适合我的简单解决方案,但当url有多个同名参数时,它就不起作用了

您还需要从视图向模板提供RequestContext请求实例。更多信息请点击此处:


我想说的是,从控制器生成下一个和上一个链接,然后将其传递到视图并从那里使用它。我将给你一个例子(更像一个伪代码):

然后在您看来,像这样使用它:

{% if contacts.has_next %}
<a href="?page={{ contacts.next_link }}">next</a>
{% endif %}
{%if contacts.has_next%}
{%endif%}

您需要返回上述GET。您可以通过调用

render_dict['GET'] = request.GET.urlencode(True)
return render_to_response('search/search.html',
                          render_dict,
                          context_instance=RequestContext(request))
然后你可以在模板中使用它来构建你的URL,例如

href="/search/client/{{ page.no }}/10/?{{ GET }}

可以创建上下文处理器,以便在应用分页的任何位置使用它

例如,在
my\u project/my\u app/context\u 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())}
将上下文处理器添加到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',
)
然后,在模板中,可以在分页时使用此选项:

<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>

{#初始/后退按钮}
{%如果页面_obj.has_previous%}
{%endif%}
{#按数字选择页面#}
{page_obj.paginator.page_range%}
{%ifequal page_obj.number%}
{%endifequal%}
{%endfor%}
{#最终/前进按钮}
{%如果页面_obj.has_next%}
{%endif%}

无论请求中有什么GET变量,它们都将附加在
?page=
GET参数之后。

这是一种简单的方法

鉴于:

path = ''
path += "%s" % "&".join(["%s=%s" % (key, value) for (key, value) in request.GET.items() if not key=='page' ])
然后在模板中:

<a href="?{% url_replace request 'page' paginator.next_page_number %}">
href="?page={{ objects.next_page_number }}&{{path}}"

使用Django的分页,保存GET参数很简单

首先将GET参数复制到变量(在视图中):

并通过上下文字典将其发送到模板:

return render_to_response(template,
                        {'request': request, 'contact': contact, 'GET_params':GET_params}, context_instance=RequestContext(request))
您需要做的第二件事是使用它,在模板中的url调用(href)中指定它-例如(扩展基本分页html以处理额外的参数条件):

{%if contacts.has_next%}
{%if GET_params%}
{%else%}
{%endif%}
{%endif%}

我认为url\u替换解决方案可以更优雅地重写为

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()
将模板字符串简化为

<a href="?{% url_replace page=paginator.next_page_number %}">

通过以下方式改进:

使用
django
中的
urlencode
而不是
urllib
,以防止
unicode
参数出现
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)
模板:

<!-- 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>

{%如果优惠券.has_previous%}
{%endif%}
第{{objects.paginator.num_pages}页中的第{{objects.number}页
{%if objects.has_next%}
{%endif%}

另一种url_编码解决方案,在本例中通过skoval00简化

我对那个版本有一些问题。第一,它不支持Unicode编码;第二,它对具有多个相同密钥的筛选器(如MultipleSelect wid)中断
{% if contacts.has_next %}
    {% if GET_params %}
        <a href="?{{GET_params.urlencode}}&amp;page={{ contacts.next_page_number }}">next</a>
    {% else %}
        <a href="?page={{ contacts.next_page_number }}">next</a>
    {% endif %}
{% endif %}
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()
<a href="?{% url_replace page=paginator.next_page_number %}">
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)
<!-- 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>
from django import template
from django.utils.html import mark_safe

register = template.Library()

@register.simple_tag(takes_context=True)
def url_replace(context, **kwargs):
    query = context['request'].GET.copy()

    for kwarg in kwargs:
        try:
            query.pop(kwarg)
        except KeyError:
            pass

    query.update(kwargs)

    return mark_safe(query.urlencode())
<a class="next" href="?{% url_replace p=objects.next_page_number%}">Next</a>
{% bootstrap_pagination page_obj extra=request.GET.urlencode %}
from urllib.parse import urlencode
from django import template

register = template.Library()

@register.simple_tag(takes_context=True)
def url_replace(context, next_page):
    query = context['request'].GET.copy().urlencode()

    if '&page=' in query:
        url = query.rpartition('&page=')[0] # equivalent to .split('page='), except more efficient 
    else:
        url = query
    return f'{url}&page={next_page}'
from urllib.parse import urlencode
from django import template

register = template.Library()

@register.simple_tag(takes_context=True)
def url_replace(context, next_page):
    if query.startswith('page') or not len(query):
        new_url = f'page={next_page}'
    elif '&page=' in query:
        get_params = query.rpartition('&page=')[0] # equivalent to .split('page='), except more efficient 
        new_url = f'{get_params}&page={next_page}'
    else:
        new_url = f'{query}&page={next_page}'
    return new_url
    @register.simple_tag(takes_context=True)
    def url_replace(context, **kwargs):
        query = context['request'].GET.copy()
        query.pop('page', None)
        query.update(kwargs)
        return query.urlencode()
@register.simple_tag(takes_context=True)
def url_replace(context, **kwargs):
    query = context['request'].GET.copy()
    for key in kwargs:
        query[key] = kwargs[key]
    return query.urlencode()
<a class="page-link" href="?{% url_replace p=1 q='bar'%}">
{% 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 %}