Изменение URL-адресов Django с дополнительными параметрами

Предположим, что у меня есть URLconf, как показано ниже, и 'foo' и 'bar' являются допустимыми значениями для page_slug.

urlpatterns = patterns('',
    (r'^page/(?P<page_slug>.*)/', 'myapp.views.someview'),
)

Затем я мог бы восстановить URL-адреса, используя ниже, правильно?

>>> from django.core.urlresolvers import reverse
>>> reverse('myapp.views.someview', kwargs={'page_slug': 'foo'})
'/page/foo/'
>>> reverse('myapp.views.someview', kwargs={'page_slug': 'bar'})
'/page/bar/'

Но что, если я изменю свой URLconf на это?

urlpatterns = patterns('',
    (r'^foo-direct/', 'myapp.views.someview', {'page_slug': 'foo'}),
    (r'^my-bar-page/', 'myapp.views.someview', {'page_slug': 'bar'}),
)

Я ожидал этого результата:

>>> from django.core.urlresolvers import reverse
>>> reverse('myapp.views.someview', kwargs={'page_slug': 'foo'})
'/foo-direct/'
>>> reverse('myapp.views.someview', kwargs={'page_slug': 'bar'})
'/my-bar-page/'

Однако это вызывает исключение NoReverseMatch. Я подозреваю, что пытаюсь сделать что-то невозможное. Любые предложения по разумному способу выполнить то, что я хочу?

Именованные URL-адреса не являются параметрами, так как я не хочу, чтобы другие приложения, которые ссылаются на них, нуждались в информации о специфике структуры URL-адресов (инкапсуляция и все такое).

Ответы

Ответ 1

Вам следует попытаться назвать ваши urlconfs. Пример:

urlpatterns = patterns('',
    url(r'^foo-direct/', 'myapp.views.someview', {'page_slug': 'foo'}, name='foo-direct'),
    url(r'^my-bar-page/', 'myapp.views.someview', {'page_slug': 'bar'}, name='bar-page'),
)

Затем просто отредактируйте свои реверсы, и вы должны заставить их работать.

>>> from django.core.urlresolvers import reverse
>>> reverse('foo-direct', kwargs={'page_slug': 'foo'})
'/foo-direct/'
>>> reverse('bar-page', kwargs={'page_slug': 'bar'})
'/my-bar-page/'

Дополнительная информация: Django Docs

Ответ 2

Вот что мы делаем.

urls.py имеет такие шаблоны

url(r'^(?P< datarealm >.*?)/json/someClass/(?P<object_id>.*?)/$', 'json_someClass_resource', ),

views.py как обратные вызовы, подобные этому

    object = SomeModel.objects.get(...)
    url= reverse('json_someClass_resource', kwargs={'object_id':object.id,'datarealm':object.datarealm.name})

Ответ 3

Именованные URL-адреса должны быть опцией. Ваш случай выделен в ссылке Django:

http://docs.djangoproject.com/en/dev/topics/http/urls/?from=olddocs#id2

Я не уверен, что дизайнеры оставили еще одну работу; они ожидали, что названные URL-адреса будут закрыты.

Могу ли я отвлечься от инкапсуляции? Благодарю. Существуют две основные причины:

  • Абстракция - никто не хочет видеть детали.
  • Безопасность - никто не должен видеть детали

Что касается 1, вы можете получить приличное количество пробега из него в python, а Django - отличный пример. Что касается 2, это интерпретируемый язык. Либо вы запускаете его там, где он написан, либо вы отправляете скомпилированные файлы .pyc. Если это действительно то, что вы делаете, тогда скомпилируйте url conf.

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