Django的可选网址参数(Django optional url parameters)

2019-07-18 06:46发布

我有一个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/是同样有效的网址格式,因此, 如果 project_id通过, 那么我就可以使用它。

因为它代表的那一刻,我收到了404,当我访问的网址不project_id参数。

Answer 1:

有几种方法。

一种方法是使用在正则表达式的非捕获组: (?:/(?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


Answer 2:

您可以使用嵌套路线

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及以上



Answer 3:

更简单的使用方法:

(?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'
),


Answer 4:

以为我会有点添加到答案。

如果你有多个URL的定义,那么你就必须单独命名他们每个人。 所以,你叫反向时,因为一个倒车指望一个参数,而其他不会失去灵活性。

另一种方法是使用正则表达式来适应可选参数:

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


Answer 5:

Django的> 2.0版

该方法是在给定的一个基本相同的虞姬“富田”富田的答案 。 受此影响,然而,这是语法:

# 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 ,你也可以通过额外的参数到视图与dict作为可选参数。 在这种情况下,您的观点将不再需要该属性的默认project_id

    ...
    path(
        'project_config/<product>/',
        views.get_product,
        name='project_config',
        {'project_id': None}
    ),
    ...

对于如何在最近的Django的版本完成后,见约URL调度的官方文档 。



Answer 6:

Django的= 2.2

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


文章来源: Django optional url parameters