Django: произвольное количество неназванных параметров urls.py - PullRequest
18 голосов
/ 30 октября 2008

У меня есть модель Django с большим количеством полей и 20000+ строк таблицы. Для облегчения восприятия человеком URL-адресов и возможности разбивать большой список на произвольные подсписки, я хотел бы иметь URL-адрес, который выглядит так:

/browse/<name1>/<value1>/<name2>/<value2>/ .... etc ....

где «имя» соответствует атрибуту модели, а «значение» - критерий поиска для этого атрибута. Каждое «имя» будет обрабатываться как категория, чтобы возвращать подмножества экземпляров модели, где категории совпадают.

Теперь это можно обрабатывать с помощью параметров GET, но я предпочитаю более удобочитаемые URL-адреса как для пользователя, так и для поисковых систем. Эти подмножества URL-адресов будут встроены на каждую страницу, на которой отображается эта модель, поэтому кажется, что стоит создать красивые URL-адреса.

В идеале каждая пара имя / значение будет передаваться в функцию представления в виде параметра с именем name1, name2 и т. Д. Однако я не верю, что можно определить именованные шаблоны с помощью сопоставленного текста регулярного выражения. Я не прав там?

Итак, похоже, мне нужно сделать что-то вроде этого:

urlpatterns = patterns('',
    url(r'^browse/(?:([\w]+)/([\w]+)/)+$', 'app.views.view', name="model_browse"),
)

Кажется, это должно соответствовать любым наборам двух пар имя / значение. Несмотря на то, что он успешно совпадает, он передает только пару фамилия / значение в качестве параметров функции представления. Я предполагаю, что каждый матч переписывает предыдущий. Предполагая, что содержащее (?: ...) + вызывает его, я вместо этого попробовал простой повторяющийся шаблон:

urlpatterns = patterns('',
    url(r'^browse/([\w]+/)+$', 'app.views.view', name="model_browse"),
)

... и получил ту же проблему, но на этот раз *args включает только последний сопоставленный шаблон.

Это ограничение для диспетчера URL Django и / или поддержки регулярных выражений в Python? Кажется, любой из этих методов должен работать. Есть ли способ достичь этого без жесткого кодирования каждого возможного атрибута модели в URL-адресе в качестве необязательного (. *) Шаблона?

Ответы [ 5 ]

14 голосов
/ 30 октября 2008

Возможность, которую вы могли бы рассмотреть, - это сопоставление всей строки возможных значений в части шаблона URL и извлечение определенных частей в вашем представлении. Как пример:

urlpatterns = patterns('',
    url(r'^browse/(?P<match>.+)/$', 'app.views.view', name='model_browse'),
)

def view(request, match):
    pieces = match.split('/')
    # even indexed pieces are the names, odd are values
    ...

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

(Отредактировано, чтобы попытаться исправить регулярное выражение.)

3 голосов
/ 30 октября 2008

Я согласен с Адамом, но я думаю, что шаблон в urls.py должен быть:

... r'^browse/(?P<match>.+)/$' ...

«\ w» будет соответствовать только символам «слова», но «.» будет соответствовать чему угодно.

0 голосов
/ 23 февраля 2016

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

url(r'^my_app/(((list\/)((\w{1,})\/(\w{1,})\/(\w{1,3})\/){1,10})+)$'

Я использовал безымянные параметры URL и повторное регулярное выражение. Не получить "не является допустимым регулярным выражением: многократное повторение" я помещаю слово в начало списка.

Я все еще работаю в представлении, получающем список. Но я думаю, что я не смогу пройтись по аргам или кваргам. Не могу сказать точно.

Мои 2 цента

0 голосов
/ 15 октября 2013

Я думаю, что ответ Адама более общий, чем мое решение, но если вы хотите использовать фиксированное количество аргументов в URL, вы также можете сделать что-то вроде этого:

В следующем примере показано, как получить все продажи за день, указав имя store и year, month и day.

urls.py

urlpatterns = patterns('',
    url(r'^baseurl/location/(?P<store>.+)/sales/(?P<year>[0-9][0-9][0-9][0-9])-(?P<month>[0-9][0-9])-(?P<day>[0-9][0-9])/$', views.DailySalesAtLocationListAPIView.as_view(), name='daily-sales-at-location'),
)

В качестве альтернативы, вы также можете использовать идентификатор магазина, изменив (?P<store>.+) на (?P<store>[0-9]+). Обратите внимание, что location и sales не являются ключевыми словами, они просто улучшают читаемость URL.

views.py

class DailySalesAtLocationListAPIView(generics.ListAPIView):
    def get(self, request, store, year, month, day):
        # here you can start using the values from the url
        print store
        print year
        print month
        print date

        # now start filtering your model

Надеюсь, это кому-нибудь поможет!

С уважением,

Michael

0 голосов
/ 01 ноября 2008

Тот же ответ пришел ко мне при чтении вопроса.

Я считаю, что представление model_browse - лучший способ отсортировать параметры запроса и использовать его в качестве универсального маршрутизатора.

...