Django可选的url参数

时间:2013-01-16 03:46:36

标签: python django django-views django-urls

我有一个像这样的Django网址:

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通过,我可以使用它。

目前看来,当我访问没有project_id参数的网址时,我得到了404.

7 个答案:

答案 0 :(得分:334)

有几种方法。

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

答案 1 :(得分:36)

您可以使用嵌套路线

Django&lt; 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&gt; = 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行,它就会影响以下网址。

为Django 1.8及以上版本编辑

答案 2 :(得分:23)

更简单的是使用:

(?P<project_id>\w+|)

&#34;(a | b)&#34;表示a或b,因此在您的情况下,它将是一个或多个单词字符(\ w +)或什么都没有。

所以它看起来像:

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

答案 3 :(得分:9)

以为我会在答案中添加一些内容。

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

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

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

答案 4 :(得分:4)

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作为可选参数。在这种情况下,您的视图不需要属性project_id的默认值:

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

有关如何完成操作在最新的Django版本中,请参见the official docs about URL dispatching

答案 5 :(得分:1)

Django = 2.2

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

答案 6 :(得分:0)

使用?工作正常,您可以检查pythex。请记住在视图方法的定义中添加参数* args和** kwargs

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