Django可选的url参数

我有这样的Djangourl:

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

和我的views.py:

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

问题是,我希望project_id参数是可选的。 我想/project_config//project_config/12345abdce/都是同样有效的url模式,所以如果 project_id被传递,那么我可以使用它。 就目前而言,如果我尝试访问没有project_id参数的url,我会得到一个404。

有几种方法。

一个是使用一个奇特的正则expression式… (?:/(?P<title>[a-zA-Z]+)/)?
使正则expression式Django URL令牌可选

另一个更容易遵循的方式是有多个符合你需求的规则,都指向相同的观点。

 urlpatterns = patterns('', url(r'^project_config/$', views.foo), url(r'^project_config/(?P<product>\w+)/$', views.foo), ulr(r'^project_config/(?P<product>\w+)/(?P<project_id>\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<product>\w+)$', include(patterns('', url(r'^$', ProductView.as_view(), name="product"), url(r'^(?P<project_id>\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<product>\w+)$', include([ url(r'^$', ProductView.as_view(), name="product"), url(r'^(?P<project_id>\w+)$', ProjectDetailView.as_view(), name="project_detail") ])), ])), ] 

这是更多的干(如果你想重命名product kwarg到product_id ,你只需要改变第4行,这将影响下面的url。

编辑为Django 1.8及以上

更简单的是使用:

 (?P<project_id>\w+|) 

“(a | b)”意思是a或b,所以在你的情况下,它将是一个或多个单词字符(\ w +)或者什么也不是。

所以它看起来像:

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

以为我会添加一些答案。

如果您有多个url定义,那么您必须分别命名每个url。 所以你在调用反向时会失去灵活性,因为一个反向会期望一个参数,而另一个则不会。

另一种使用正则expression式来容纳可选参数的方法:

 r'^project_config/(?P<product>\w+)/((?P<project_id>\w+)/)?$'