问题:Django可选的url参数
我有一个像这样的Django URL:
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 。
回答 0
有几种方法。
一种是在正则表达式中使用非捕获组:使正则 (?:/(?P<title>[a-zA-Z]+)/)?
表达式Django URL令牌为可选
另一种更容易遵循的方法是拥有多个符合您需求的规则,所有规则都指向同一视图。
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
回答 1
您可以使用嵌套路线
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")
])),
])),
]
这比DRY要多得多(假设您要将product
kwarg 重命名为product_id
,只需更改第4行,它就会影响以下网址。
针对Django 1.8及更高版本进行了编辑
回答 2
更简单的是使用:
(?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'
),
回答 3
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
...
使用,kwargs
dict
project_id
...
path(
'project_config/<product>/',
views.get_product,
kwargs={'project_id': None},
name='project_config'
),
...
有关如何在最新的Django版本中完成此操作的信息,请参阅有关URL调度的官方文档。
回答 4
以为我会在答案中加点。
如果您有多个URL定义,则必须分别命名每个。因此,当调用反向时,您会失去灵活性,因为一个反向将需要一个参数,而另一个则不会。
使用正则表达式来容纳可选参数的另一种方法:
r'^project_config/(?P<product>\w+)/((?P<project_id>\w+)/)?$'
回答 5
的Django = 2.2
urlpatterns = [
re_path(r'^project_config/(?:(?P<product>\w+)/(?:(?P<project_id>\w+)/)/)?$', tool.views.ProjectConfig, name='project_config')
]
回答 6
用 ?工作正常,您可以检查pythex。请记住在视图方法的定义中添加参数* args和** kwargs
url('project_config/(?P<product>\w+)?(/(?P<project_id>\w+/)?)?', tool.views.ProjectConfig, name='project_config')