Django – Как передать несколько аргументов в тег шаблона URL

В моем urls.py у меня есть:

(r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/section/(?P<slug>[-\w]+)/$', 
    'paper.views.issue_section_detail', 
    {}, 
    'paper_issue_section_detail'
),

и я пытаюсь сделать это в шаблоне:

{% url paper_issue_section_detail issue.pub_date.year,issue.pub_date.month,issue.pub_date.day,section_li.slug %}

но я получаю эту ошибку:

TemplateSyntaxError
Caught an exception while rendering: Reverse for 'paper_issue_section_detail' with arguments '(2010, 1, 22, u'business')' and keyword arguments '{}' not found.

Однако, если я изменю шаблон URL, чтобы он требовал только один аргумент, он работает нормально. то есть:

(r'^(?P<year>\d{4})/$', 
    'paper.views.issue_section_detail', 
    {}, 
    'paper_issue_section_detail'
),

и:

{% url paper_issue_section_detail issue.pub_date.year %}

Таким образом, кажется, что жалуются, когда я передаю более одного аргумента с использованием тега шаблона «url» - я получаю ту же ошибку с двумя аргументами. Есть ли другой способ передать несколько аргументов? Я попытался передать именованные аргументы ключевого слова, и это приводит к аналогичной ошибке.

Что бы это ни стоило, связанное представление начинается так:

def issue_section_detail(request, year, month, day, slug):

Как передать тегу шаблона URL более одного аргумента?


person Phil Gyford    schedule 22.01.2010    source источник


Ответы (3)


Проблема заключается в /(?P<month>\d{2})/ части конфигурации вашего URL. Он допускает только ровно две цифры (\d{2}), а issue.pub_date.month — только одну цифру.

Вы можете либо разрешить использование одной цифры в URL-адресе (но это нарушит принцип уникальных URL-адресов, /2010/1/... будет таким же, как /2010/01/...), либо передать две цифры в аргументе месяца в теге шаблона URL-адреса.
Вы можете использовать метод date для достижения согласованного форматирования объектов даты. Используйте тег URL следующим образом:

{% url paper_issue_section_detail issue.pub_date|date:"Y",issue.pub_date|date:"m",issue.pub_date|date:"d",section_li.slug %}

Посмотрите на аргумент месяца и дня: он всегда будет отображаться в виде двух цифр (при необходимости с начальным нулем). Посмотрите документацию по тегу now, чтобы увидеть какие варианты возможны для фильтра date.

person Gregor Müllegger    schedule 22.01.2010
comment
Звучит здорово - я действительно не хочу менять возможное форматирование URL-адреса. Но когда я делаю issue.pub_date.month|date:m, тогда в URL/представление передается пустая строка. - person Phil Gyford; 23.01.2010
comment
Вы правы - извините. Я явно ошибся в исходном посте. Я исправил тег url. Вы должны использовать issue.pub_date|date:"m" вместо issue.pub_date.month|date:"m". Фильтр date работает с datetime объектами (атрибут pub_date), а не с целыми числами (атрибут pub_date.month). - person Gregor Müllegger; 23.01.2010
comment
Дох, конечно, я тоже должен был это заметить. Большое спасибо за помощь, Грегор. - person Phil Gyford; 23.01.2010

У меня была та же проблема (я использую Django 1.3.1), и я попробовал предложение Грегора Мюллеггера, но это не сработало по двум причинам:

  • не должно быть запятых между значениями года, месяца и дня
  • мой общий вид на основе классов, кажется, принимает только аргументы ключевого слова

Таким образом, единственным рабочим решением было:

{% url news_detail slug=object.slug year=object.date|date:"Y" month=object.date|date:"m" day=object.date|date:"d" %}
person Vlad T.    schedule 11.03.2012

Ваше выражение месяца (?P<month>\d{2}), но вы отправляете ему аргумент 1. 1 не соответствует \d{2}, поэтому преобразователь URL не находит ваше представление.

Попробуйте изменить выражение месяца на \d{1,2} (или что-то в этом роде).

person Seth    schedule 22.01.2010
comment
Большое спасибо за ваше предложение, Сет - я не установил связь между регулярным выражением и тем, что я пытался ему передать. Но я не хотел ослаблять ограничение на URL-адрес, поэтому сейчас я меняю формат того, что я передаю, используя предложение Грегора Мюллеггера. - person Phil Gyford; 23.01.2010