首页 文章

Django可选的url参数

提问于
浏览
132

我有一个像这样的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/ 都是同等有效的url模式,以便传递 IF project_id ,然后我可以使用它 . 就目前而言,如果我尝试访问没有 project_id 参数的URL,我会得到404 .

4 回答

  • 21

    有几种方法 .

    一种是在正则表达式中使用非捕获组: (?:/(?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),
        ulr(r'^project_config/(?P<product>\w+)/(?P<project_id>\w+)/$', views.foo),
    )
    

    请注意,在您的视图中,您还需要为可选的URL参数设置默认值,否则您将收到错误消息:

    def foo(request, optional_parameter=''):
        # Your code goes here
    
  • 314

    You can use nested routes

    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行,它将影响以下URL .

    编辑Django 1.8及以上版本

  • 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'
    ),
    
  • 36

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

    如果您有多个URL定义,那么您必须分别为每个URL定义 . 因此,在调用reverse时会失去灵活性,因为一个反向将期望一个参数而另一个反之则不会 .

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

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

相关问题