Python Django 可选 url 参数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14351048/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 11:09:32  来源:igfitidea点击:

Django optional url parameters

pythondjangodjango-viewsdjango-urls

提问by Darwin Tech

I have a Django URL like this:

我有一个像这样的 Django URL:

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

views.py:

视图.py:

def ProjectConfig(request, product, project_id=None, template_name='project.html'):
    ...
    # do stuff

The problem is that I want the project_idparameter to be optional.

问题是我希望project_id参数是可选的。

I want /project_config/and /project_config/12345abdce/to be equally valid URL patterns, so that ifproject_idis passed, thenI can use it.

我想要/project_config/并且/project_config/12345abdce/是同样有效的 URL 模式,以便如果project_id通过,那么我可以使用它。

As it stands at the moment, I get a 404 when I access the URL without the project_idparameter.

目前,当我访问没有project_id参数的 URL 时,我得到 404 。

采纳答案by Yuji 'Tomita' Tomita

There are several approaches.

有几种方法。

One is to use a non-capturing group in the regex: (?:/(?P<title>[a-zA-Z]+)/)?
Making a Regex Django URL Token Optional

一种是在正则表达式中使用非捕获组: (?:/(?P<title>[a-zA-Z]+)/)?
Making a Regex Django URL Token Optional

Another, easier to follow way is to have multiple rules that matches your needs, all pointing to the same view.

另一种更容易遵循的方法是拥有多个符合您需求的规则,所有规则都指向同一个视图。

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),
)

Keep in mind that in your view you'll also need to set a default for the optional URL parameter, or you'll get an error:

请记住,在您的视图中,您还需要为可选的 URL 参数设置默认值,否则会出现错误:

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

回答by tarequeh

Thought I'd add a bit to the answer.

以为我会在答案中添加一点。

If you have multiple URL definitions then you'll have to name each of them separately. So you lose the flexibility when calling reverse since one reverse will expect a parameter while the other won't.

如果您有多个 URL 定义,则必须分别命名它们。因此,您在调用 reverse 时失去了灵活性,因为一个反向需要一个参数,而另一个则不需要。

Another way to use regex to accommodate the optional parameter:

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

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

回答by Jacob Valenta

You can use nested routes

您可以使用嵌套路由

Django <1.8

姜戈 <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

姜戈 >=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")
        ])),
    ])),
]

This is a lot more DRY (Say you wanted to rename the productkwarg to product_id, you only have to change line 4, and it will affect the below URLs.

这更加 DRY(假设您想将productkwarg重命名为product_id,您只需更改第 4 行,它将影响以下 URL。

Edited for Django 1.8 and above

为 Django 1.8 及以上版本编辑

回答by Juan José Brown

Even simpler is to use:

更简单的是使用:

(?P<project_id>\w+|)

The "(a|b)" means a or b, so in your case it would be one or more word characters (\w+) or nothing.

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

So it would look like:

所以它看起来像:

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

回答by jojo

Django > 2.0 version:

Django > 2.0 版本

The approach is essentially identical with the one given in Yuji 'Tomita' Tomita's Answer. Affected, however, is the syntax:

该方法与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
    ...

Using path()you can also pass extra arguments to a viewwith the optional argument kwargsthat is of type dict. In this case your view would not need a default for the attribute project_id:

使用path()你也可以通过额外的参数到视图与可选的参数kwargs是类型dict。在这种情况下,您的视图不需要属性的默认值project_id

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

For how this is done in the most recent Django version, see the official docs about URL dispatching.

有关如何在最新的 Django 版本中完成此操作,请参阅有关 URL 调度的官方文档

回答by AzizAhmad

Django = 2.2

姜戈 = 2.2

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

回答by franciscorode

Use ? work well, you can check on pythex. Remember to add the parameters *args and **kwargs in the definition of the view methods

用 ?运行良好,您可以检查pythex。记得在视图方法的定义中添加参数 *args 和 **kwargs

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