Параметры необязательного URL-адреса Django

У меня есть URL-адрес Django:

url( r'^project_config/(?P\w+)/(?P\w+)/$', 'tool.views.ProjectConfig', name='project_config' ), 

и мои view.py:

 def ProjectConfig(request, product, project_id=None, template_name='project.html'): ... # do stuff 

Проблема в том, что я хочу, чтобы параметр project_id был необязательным. Я хотел бы, чтобы /project_config/ и /project_config/12345abdce/ были одинаково действительными шаблонами url, поэтому IF project_id передан, тогда я могу его использовать. Поскольку он стоит на данный момент, я получаю 404, если попытаюсь получить доступ к URL-адресу без параметра project_id .

Существует несколько подходов.

Один из них – использовать причудливое регулярное выражение … (?:/(?P[a-zA-Z]+)/)?
Создание маркера URL-адреса регулярного выражения Django

Другой, более простой путь – это иметь несколько правил, которые соответствуют вашим потребностям, и все они указывают на одно и то же представление.

 urlpatterns = patterns('', url(r'^project_config/$', views.foo), url(r'^project_config/(?P\w+)/$', views.foo), ulr(r'^project_config/(?P\w+)/(?P\w+)/$', views.foo), ) 

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

 def foo(request, optional_parameter=''): # Your code goes here 

Вы можете использовать вложенные маршруты

Django <1,8

 urlpatterns = patterns('' url(r'^project_config/', include(patterns('', url(r'^$', ProjectConfigView.as_view(), name="project_config") url(r'^(?P\w+)$', include(patterns('', url(r'^$', ProductView.as_view(), name="product"), url(r'^(?P\w+)$', ProjectDetailView.as_view(), name="project_detail") ))), ))), ) 

Django> = 1,8

 urlpatterns = [ url(r'^project_config/', include([ url(r'^$', ProjectConfigView.as_view(), name="project_config") url(r'^(?P\w+)$', include([ url(r'^$', ProductView.as_view(), name="product"), url(r'^(?P\w+)$', ProjectDetailView.as_view(), name="project_detail") ])), ])), ] 

Это намного больше DRY (скажем, вы хотели переименовать product kwarg в product_id , вам нужно только изменить строку 4, и это повлияет на приведенные ниже URL-адреса.

Отредактировано для Django 1.8 и выше

Еще проще использовать:

 (?P\w+|) 

«(A | b)» означает a или b, поэтому в вашем случае это будет один или несколько символов слова (\ w +) или ничего.

Таким образом, это будет выглядеть так:

 url( r'^project_config/(?P\w+)/(?P\w+|)/$', 'tool.views.ProjectConfig', name='project_config' ), 

Думал, я бы добавил немного ответа.

Если у вас несколько определений URL-адресов, вам нужно будет указать их отдельно. Таким образом, вы теряете гибкость при вызове reverse, поскольку один обратный будет ожидать параметр, а другой – нет.

Другой способ использования регулярного выражения для размещения необязательного параметра:

 r'^project_config/(?P\w+)/((?P\w+)/)?$' 
Interesting Posts
Давайте будем гением компьютера.