我有一个这样的 Django URL:
url(
r'^project_config/(?P<product>\w+)/(?P<project_id>\w+)/$',
'tool.views.ProjectConfig',
name='project_config'
),
视图.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
被传递,then 我可以使用它。
就目前而言,当我访问没有 project_id
参数的 URL 时,我得到一个 404。
有几种方法。
一种是在正则表达式中使用非捕获组:(?:/(?P<title>[a-zA-Z]+)/)?
Making a Regex Django URL Token Optional
另一种更容易遵循的方法是拥有多个符合您需求的规则,所有规则都指向同一个视图。
urlpatterns = patterns('',
url(r'^project_config/$', views.foo),
url(r'^project_config/(?P<product>\w+)/$', views.foo),
url(r'^project_config/(?P<product>\w+)/(?P<project_id>\w+)/$', views.foo),
)
请记住,在您的视图中,您还需要为可选的 URL 参数设置默认值,否则您会收到错误消息:
def foo(request, optional_parameter=''):
# Your code goes here
Django > 2.0 版本:
该方法与 Yuji 'Tomita' Tomita's Answer 中给出的方法基本相同。然而,受影响的是语法:
# URLconf
...
urlpatterns = [
path(
'project_config/<product>/',
views.get_product,
name='project_config'
),
path(
'project_config/<product>/<project_id>/',
views.get_product,
name='project_config'
),
]
# View (in views.py)
def get_product(request, product, project_id='None'):
# Output the appropriate product
...
使用 path()
,您还可以将 pass extra arguments to a view 与 dict
类型的可选参数 kwargs
结合使用。在这种情况下,您的视图不需要属性 project_id
的默认值:
...
path(
'project_config/<product>/',
views.get_product,
kwargs={'project_id': None},
name='project_config'
),
...
在最新的 Django 版本中如何做到这一点,请参阅 the official docs about URL dispatching。
dict
的情况下,路径中还有 project_id
。这可能会导致看似奇怪的行为,因为将始终使用 dict
中提供的参数(如果我没记错的话)。
您可以使用嵌套路由
姜戈 <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")
])),
])),
]
这更 DRY(假设您想将 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'
),
None
。这意味着您不能为此依赖视图签名中的默认值:您必须在内部显式测试它并进行分配。
以为我会在答案中添加一点。
如果您有多个 URL 定义,则必须分别命名它们。所以你在调用 reverse 时失去了灵活性,因为一个 reverse 会需要一个参数,而另一个不会。
另一种使用正则表达式来容纳可选参数的方法:
r'^project_config/(?P<product>\w+)/((?P<project_id>\w+)/)?$'
Reverse for 'edit_too_late' with arguments '()' and keyword arguments '{'pk': 128}' not found. 1 pattern(s) tried: ['orders/cannot_edit/((?P<pk>\\d+)/)?$']
姜戈 = 2.2
urlpatterns = [
re_path(r'^project_config/(?:(?P<product>\w+)/(?:(?P<project_id>\w+)/)/)?$', tool.views.ProjectConfig, name='project_config')
]
利用 ?运行良好,您可以查看 pythex。记得在视图方法的定义中添加参数 *args 和 **kwargs
url('project_config/(?P<product>\w+)?(/(?P<project_id>\w+/)?)?', tool.views.ProjectConfig, name='project_config')
不定期副业成功案例分享