Django: Как вы можете получить текущее имя тега URL (для разбиения на страницы)?

Я пытаюсь выполнить разбиение на страницы с параметром страницы в URL-адресе (вместо параметра GET). Я также хочу, чтобы моя нумерация страниц была общим кодом для нескольких разных шаблонов.

Учитывая это, я думаю, что мне нужно сделать что-то вроде этого:

URL.py:

url(r'^alias/page;(?P<page>[0-9]+)/(?P<id>.*)$', alias.get, name="alias"),

шаблоны/псевдоним.html:

<div>...stuff...</div>
{% include "paginator.html" %}

шаблоны/paginator.html :

{% if page_obj.has_previous or page_obj.has_next %}
{% load filters %}
<div class="pagination clear">
    {% if page_obj.has_previous %}
        <a href="{% url somemagic %}" class="prev">&lsaquo;&lsaquo; previous</a>
...

Что такое somemagic?

Предположим, я хочу сохранить свой URL-адрес таким же, за исключением установки страницы page_obj.previous_page_number


person Paul Tarjan    schedule 01.08.2009    source источник
comment
Вы уже рассматривали django-pagination как альтернативный вариант? code.google.com/p/django-pagination   -  person Thomas Schreiber    schedule 02.08.2009
comment
Да, он использует ?page=4, но у меня есть другие постоянные параметры получения, которые будут мешать.   -  person Paul Tarjan    schedule 02.08.2009
comment
ваши другие параметры получения «страница»? django-pagination сохранит все остальные параметры получения без изменений. я использую его в каждом приложении когда-либо. вы не можете проиграть, если будете смотреть эти скринкасты. eflorenzano.com/blog/post/first-two-django-screencasts   -  person Brandon Henry    schedule 22.10.2009


Ответы (2)


Изменить:

Вам нужно, чтобы somemagic была переменной с именем текущего представления.

Попробуй это:

{% with request.path_info|resolve_url_name as current_view %}
    {% url current_view page_obj.previous_page_number object.id %}
{% endwith %}

Вы можете заставить это работать с некоторым кодом из фрагментов django:

  1. Тег шаблона URL разрешения переменной Заставляет тег {% url %} разрешать переменные из контекста.
  2. Разрешить URL-адреса для имени представления Функция resolve_to_name(path) возвращает имя представления для path. Вам просто нужно создать фильтр, который использует эту функцию.

Это решение не будет работать с такими URL-адресами, как:

'alias/param1_regexp/param2_regexp/page;(?P<page>[0-9]+)/(?P<id>.*)$'

потому что вы понятия не имеете о param1 и param2.

Можно внести изменения в приведенные выше фрагменты django, чтобы такие URL-адреса работали:

Изменения первого фрагмента:

from django.template import defaulttags, VariableDoesNotExist, Variable

class ResolvingURLNode(defaulttags.URLNode):
    def render(self, context):
        original_view_name = self.view_name
        try:
            resolved = Variable(self.view_name).resolve(context)
            if len(resolved) > 1:                
                self.view_name = resolved[0]
                if resolved[1]:
                    self.args = [Variable(arg) for arg in resolved[1]]
            elif len(resolved) > 0:
                self.view_name = resolved[0]
            else:
                self.view_name = resolved

        except VariableDoesNotExist:
            pass
        ret = super(defaulttags.URLNode, self).render(context)
        # restore view_name in case this node is reused (e.g in a loop) in
        # which case the variable might resolve to something else in the next iteration)
        self.view_name = original_view_name
        return ret

defaulttags.URLNode = ResolvingURLNode

Изменения второго фрагмента

from django.core.urlresolvers import RegexURLResolver, RegexURLPattern, Resolver404, get_resolver

__all__ = ('resolve_to_name',)

def _pattern_resolve_to_name(self, path):
    match = self.regex.search(path)
    if match:
        name = ""
        if self.name:
            name = self.name
        elif hasattr(self, '_callback_str'):
            name = self._callback_str
        else:
            name = "%s.%s" % (self.callback.__module__, self.callback.func_name)
        if len(match.groups()) > 0:
            groups = match.groups()
        else:
            groups = None
        return name, groups


def _resolver_resolve_to_name(self, path):
    tried = []
    match = self.regex.search(path)
    if match:
        new_path = path[match.end():]
        for pattern in self.url_patterns:
            try:
                resolved = pattern.resolve_to_name(new_path)
                if resolved:
                    name, groups = resolved
                else:
                    name = None
            except Resolver404, e:
                tried.extend([(pattern.regex.pattern + '   ' + t) for t in e.args[0 ['tried']])
            else:
                if name:
                    return name, groups
                tried.append(pattern.regex.pattern)
        raise Resolver404, {'tried': tried, 'path': new_path}


# here goes monkeypatching
RegexURLPattern.resolve_to_name = _pattern_resolve_to_name
RegexURLResolver.resolve_to_name = _resolver_resolve_to_name


def resolve_to_name(path, urlconf=None):
    return get_resolver(urlconf).resolve_to_name(path)

По сути, resolve_to_name возвращает имя представления и его параметры в виде кортежа, а new {% url myvar %} берет этот кортеж и использует его для обратного пути с именем представления и его параметрами.

Если вам не нравится подход к фильтру, это также можно сделать с помощью специального промежуточного программного обеспечения.


Предыдущий ответ

Вы должны проверить django-pagination, это действительно хорошее приложение django, простое в использовании и выполняющее свою работу.

С разбиением на страницы django код для разбиения на страницы итерируемого объекта будет таким:

{% load pagination_tags %}

{% autopaginate myiterable 10 %} <!-- 10 elements per page -->

{% for item in myiterable %} RENDERING CONTENT {% endfor %}

{% paginate %} <!-- this renders the links to navigate through the pages -->

myiterable может быть чем угодно, что является итерируемым: список, кортеж, набор запросов и т. д.

Страница проекта в googlecode: http://code.google.com/p/django-pagination/

person Guillem Gelabert    schedule 26.08.2009
comment
да, я использовал это, но у него есть ?page= как способ разбивки на страницы, который не работает для меня, поскольку мои URL-адреса уже имеют некоторые параметры запроса, которые важно сохранить. - person Paul Tarjan; 26.08.2009
comment
Интересно, почему этот тип {% url %} не используется в реальном django? А что касается подхода промежуточного программного обеспечения, будет ли он менее инвазивным? Кажется, что переписывание ядра {% url %} может что-то сломать в будущем. - person Paul Tarjan; 30.08.2009
comment
В промежуточном программном обеспечении вместо использования request.path_info|resolve_to_url вы вызовете resolve_to_url(request.path_info) в методе промежуточного программного обеспечения process_request(request) и добавите его в запрос как пользовательскую переменную. Тогда он будет доступен в любом шаблоне вашего проекта. Новый {% url %} завершится ошибкой, если у вас есть представление и переменная с одинаковыми именами. Этого можно избежать, создав собственный тег шаблона {% myurl %} и используя его или тег по умолчанию по мере необходимости. - person Guillem Gelabert; 31.08.2009

Это будет примерно следующее. За исключением того, что я не знаю, что вы подразумеваете под идентификатором, поэтому я просто указал общий идентификатор объекта. Синтаксис URL-адреса: {% url view_name param1 param2 ... %}

{% url alias page_obj.previous_page_number object.id %}

Обновленная база в соответствии с вашими потребностями:

{% url alias page_obj.previous_page_number object.id as prev_url %}
{% include "paginator.html" %}
...
{% if page_obj.has_previous %}
        <a href="{{prev_url}}" class="prev">&lsaquo;&lsaquo; previous</a>
person Jason Christa    schedule 02.08.2009
comment
Но pagination.html будет включен из многих других файлов для многих других URL-адресов (с другими именами шаблонов). Так что я не могу просто поставить псевдоним там. - person Paul Tarjan; 02.08.2009