标签归档:django-urls

对于Django 2.0,在urls.py中使用path()或url()更好吗?

问题:对于Django 2.0,在urls.py中使用path()或url()更好吗?

在django在线类中,讲师让我们使用该url()函数调用视图并使用urlpatterns列表中的正则表达式。我在YouTube上看到了其他示例。例如

from django.contrib import admin
from django.urls import include
from django.conf.urls import url

urlpatterns = [
    path('admin/', admin.site.urls),
    url(r'^polls/', include('polls.urls')),
]


#and in polls/urls.py

urlpatterns = [        
    url(r'^$', views.index, name="index"),
]

但是,在阅读Django教程时,他们path()改用例如:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name="index"),        
]

此外,正则表达式似乎不适用于该path()函数,因为使用path(r'^$', views.index, name="index")将找不到mysite.com/polls/视图。

使用path()没有正则表达式匹配的正确方法是正确的吗?是url()更强大,但更复杂,所以他们正在使用path()与开始我们吗?还是针对不同工作使用不同工具的情况?

In a django online course, the instructor has us use the url() function to call views and utilize regular expressions in the urlpatterns list. I’ve seen other examples on youtube of this. e.g.

from django.contrib import admin
from django.urls import include
from django.conf.urls import url

urlpatterns = [
    path('admin/', admin.site.urls),
    url(r'^polls/', include('polls.urls')),
]


#and in polls/urls.py

urlpatterns = [        
    url(r'^$', views.index, name="index"),
]

However, in going through the Django tutorial, they use path() instead e.g.:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name="index"),        
]

Furthermore regular expressions don’t seem to work with the path() function as using a path(r'^$', views.index, name="index") won’t find the mysite.com/polls/ view.

Is using path() without regex matching the proper way going forward? Is url() more powerful but more complicated so they’re using path() to start us out with? Or is it a case of different tools for different jobs?


回答 0

从Django文档获取url

url(regex, view, kwargs=None, name=None)此函数是的别名django.urls.re_path()。在将来的版本中可能不推荐使用。

path和之间的主要区别re_pathpath使用不带正则表达式的路由

您可以re_path用于复杂的正则表达式调用,也可以仅path用于更简单的查找

From Django documentation for url

url(regex, view, kwargs=None, name=None) This function is an alias to django.urls.re_path(). It’s likely to be deprecated in a future release.

Key difference between path and re_path is that path uses route without regex

You can use re_path for complex regex calls and use just path for simpler lookups


回答 1

django.urls.path()功能允许使用更简单,更易读的URL路由语法。例如,此示例来自先前的Django版本:

url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive)

可以写成:

path('articles/<int:year>/', views.year_archive)

django.conf.urls.url() 以前版本中的功能现在可以作为django.urls.re_path()。保留旧位置是为了向后兼容,而不会很快淘汰。django.conf.urls.include()现在django.urls可以从导入旧功能,因此您可以使用:

from django.urls import include, path, re_path

URLconfs中。进一步阅读django doc

The new django.urls.path() function allows a simpler, more readable URL routing syntax. For example, this example from previous Django releases:

url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive)

could be written as:

path('articles/<int:year>/', views.year_archive)

The django.conf.urls.url() function from previous versions is now available as django.urls.re_path(). The old location remains for backwards compatibility, without an imminent deprecation. The old django.conf.urls.include() function is now importable from django.urls so you can use:

from django.urls import include, path, re_path

in the URLconfs. For further reading django doc


回答 2

pathDjango 2.0只是几周前才发布的新功能。大多数教程都不会针对新语法进行更新。

当然,这应该是一种更简单的处理方式。我不会说URL更强大,但是您应该能够以任何一种格式表示模式。

path is simply new in Django 2.0, which was only released a couple of weeks ago. Most tutorials won’t have been updated for the new syntax.

It was certainly supposed to be a simpler way of doing things; I wouldn’t say that URL is more powerful though, you should be able to express patterns in either format.


回答 3

正则表达式似乎不适用于path()具有以下参数的函数:path(r'^$', views.index, name="index")

应该是这样的:path('', views.index, name="index")

第一个参数必须为空才能输入正则表达式。

Regular expressions don’t seem to work with the path() function with the following arguments: path(r'^$', views.index, name="index").

It should be like this: path('', views.index, name="index").

The 1st argument must be blank to enter a regular expression.


回答 4

Path是Django 2.0的新功能。在这里解释:https : //docs.djangoproject.com/en/2.0/releases/2.0/#whats-new-2-0

看起来更像pythonic方式,并允许在传递给视图的参数中不使用正则表达式…例如,您可以使用int()函数。

Path is a new feature of Django 2.0. Explained here : https://docs.djangoproject.com/en/2.0/releases/2.0/#whats-new-2-0

Look like more pythonic way, and enable to not use regular expression in argument you pass to view… you can ue int() function for exemple.


回答 5

从v2.0开始,许多用户正在使用path,但是我们可以使用path或url。例如,在django 2.1.1中,可以通过url映射到函数

from django.contrib import admin
from django.urls import path

from django.contrib.auth import login
from posts.views import post_home
from django.conf.urls import url

urlpatterns = [
    path('admin/', admin.site.urls),
    url(r'^posts/$', post_home, name='post_home'),

]

其中posts是应用程序,而post_home是views.py中的函数

From v2.0 many users are using path, but we can use either path or url. For example in django 2.1.1 mapping to functions through url can be done as follows

from django.contrib import admin
from django.urls import path

from django.contrib.auth import login
from posts.views import post_home
from django.conf.urls import url

urlpatterns = [
    path('admin/', admin.site.urls),
    url(r'^posts/$', post_home, name='post_home'),

]

where posts is an application & post_home is a function in views.py


Django URLs TypeError:对于include(),视图必须是可调用的或列表/元组

问题:Django URLs TypeError:对于include(),视图必须是可调用的或列表/元组

升级到Django 1.10后,出现错误:

TypeError: view must be a callable or a list/tuple in the case of include().

我的urls.py如下:

from django.conf.urls import include, url

urlpatterns = [
    url(r'^$', 'myapp.views.home'),
    url(r'^contact/$', 'myapp.views.contact'),
    url(r'^login/$', 'django.contrib.auth.views.login'),
]

完整的回溯是:

Traceback (most recent call last):
  File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/utils/autoreload.py", line 226, in wrapper
    fn(*args, **kwargs)
  File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/core/management/commands/runserver.py", line 121, in inner_run
    self.check(display_num_errors=True)
  File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/core/management/base.py", line 385, in check
    include_deployment_checks=include_deployment_checks,
  File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/core/management/base.py", line 372, in _run_checks
    return checks.run_checks(**kwargs)
  File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/core/checks/registry.py", line 81, in run_checks
    new_errors = check(app_configs=app_configs)
  File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/core/checks/urls.py", line 14, in check_url_config
    return check_resolver(resolver)
  File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/core/checks/urls.py", line 24, in check_resolver
    for pattern in resolver.url_patterns:
  File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/utils/functional.py", line 35, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/urls/resolvers.py", line 310, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
  File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/utils/functional.py", line 35, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/urls/resolvers.py", line 303, in urlconf_module
    return import_module(self.urlconf_name)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/importlib/__init__.py", line 37, in import_module
    __import__(name)
  File "/Users/alasdair/dev/urlproject/urlproject/urls.py", line 28, in <module>
    url(r'^$', 'myapp.views.home'),
  File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/conf/urls/__init__.py", line 85, in url
    raise TypeError('view must be a callable or a list/tuple in the case of include().')
TypeError: view must be a callable or a list/tuple in the case of include().

After upgrading to Django 1.10, I get the error:

TypeError: view must be a callable or a list/tuple in the case of include().

My urls.py is as follows:

from django.conf.urls import include, url

urlpatterns = [
    url(r'^$', 'myapp.views.home'),
    url(r'^contact/$', 'myapp.views.contact'),
    url(r'^login/$', 'django.contrib.auth.views.login'),
]

The full traceback is:

Traceback (most recent call last):
  File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/utils/autoreload.py", line 226, in wrapper
    fn(*args, **kwargs)
  File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/core/management/commands/runserver.py", line 121, in inner_run
    self.check(display_num_errors=True)
  File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/core/management/base.py", line 385, in check
    include_deployment_checks=include_deployment_checks,
  File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/core/management/base.py", line 372, in _run_checks
    return checks.run_checks(**kwargs)
  File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/core/checks/registry.py", line 81, in run_checks
    new_errors = check(app_configs=app_configs)
  File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/core/checks/urls.py", line 14, in check_url_config
    return check_resolver(resolver)
  File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/core/checks/urls.py", line 24, in check_resolver
    for pattern in resolver.url_patterns:
  File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/utils/functional.py", line 35, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/urls/resolvers.py", line 310, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
  File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/utils/functional.py", line 35, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/urls/resolvers.py", line 303, in urlconf_module
    return import_module(self.urlconf_name)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/importlib/__init__.py", line 37, in import_module
    __import__(name)
  File "/Users/alasdair/dev/urlproject/urlproject/urls.py", line 28, in <module>
    url(r'^$', 'myapp.views.home'),
  File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/conf/urls/__init__.py", line 85, in url
    raise TypeError('view must be a callable or a list/tuple in the case of include().')
TypeError: view must be a callable or a list/tuple in the case of include().

回答 0

Django 1.10不再允许您'myapp.views.home'在URL模式中将视图指定为字符串(例如)。

解决方案是更新您urls.py的视图以包含可调用的视图。这意味着您必须在中导入视图urls.py。如果您的URL模式没有名称,那么现在是添加名称的好时机,因为用虚线python路径进行反向操作不再起作用。

from django.conf.urls import include, url

from django.contrib.auth.views import login
from myapp.views import home, contact

urlpatterns = [
    url(r'^$', home, name='home'),
    url(r'^contact/$', contact, name='contact'),
    url(r'^login/$', login, name='login'),
]

如果有很多视图,则不方便分别导入它们。一种替代方法是从您的应用程序导入视图模块。

from django.conf.urls import include, url

from django.contrib.auth import views as auth_views
from myapp import views as myapp_views

urlpatterns = [
    url(r'^$', myapp_views.home, name='home'),
    url(r'^contact/$', myapp_views.contact, name='contact'),
    url(r'^login/$', auth_views.login, name='login'),
]

请注意,我们已经使用as myapp_viewsas auth_views,这允许我们views.py从多个应用程序导入,而不会发生冲突。

有关的更多信息,请参见Django URL调度程序文档urlpatterns

Django 1.10 no longer allows you to specify views as a string (e.g. 'myapp.views.home') in your URL patterns.

The solution is to update your urls.py to include the view callable. This means that you have to import the view in your urls.py. If your URL patterns don’t have names, then now is a good time to add one, because reversing with the dotted python path no longer works.

from django.conf.urls import include, url

from django.contrib.auth.views import login
from myapp.views import home, contact

urlpatterns = [
    url(r'^$', home, name='home'),
    url(r'^contact/$', contact, name='contact'),
    url(r'^login/$', login, name='login'),
]

If there are many views, then importing them individually can be inconvenient. An alternative is to import the views module from your app.

from django.conf.urls import include, url

from django.contrib.auth import views as auth_views
from myapp import views as myapp_views

urlpatterns = [
    url(r'^$', myapp_views.home, name='home'),
    url(r'^contact/$', myapp_views.contact, name='contact'),
    url(r'^login/$', auth_views.login, name='login'),
]

Note that we have used as myapp_views and as auth_views, which allows us to import the views.py from multiple apps without them clashing.

See the Django URL dispatcher docs for more information about urlpatterns.


回答 1

该错误仅意味着myapp.views.home不能调用它,就像函数一样。它实际上是一个字符串。当您的解决方案在django 1.9中运行时,它仍然发出警告,说它将从版本1.10开始弃用,这就是发生的一切。通过@Alasdair先前的溶液中导入必要的视图函数到脚本通过任一 from myapp import views as myapp_viewsfrom myapp.views import home, contact

This error just means that myapp.views.home is not something that can be called, like a function. It is a string in fact. While your solution works in django 1.9, nevertheless it throws a warning saying this will deprecate from version 1.10 onwards, which is exactly what has happened. The previous solution by @Alasdair imports the necessary view functions into the script through either from myapp import views as myapp_views or from myapp.views import home, contact


回答 2

如果视图和模块的名称冲突,也可能会出现此错误。我将我的视图文件分发到views文件夹下,/views/view1.py, /views/view2.py并在view2.py中导入了一个名为table.py的模型时遇到了错误,该模型恰巧是view1.py中的视图名称。因此,命名视图功能 v_table(request,id) 很有帮助。

You may also get this error if you have a name clash of a view and a module. I’ve got the error when i distribute my view files under views folder, /views/view1.py, /views/view2.py and imported some model named table.py in view2.py which happened to be a name of a view in view1.py. So naming the view functions as v_table(request,id) helped.


回答 3

您的代码是

urlpatterns = [
    url(r'^$', 'myapp.views.home'),
    url(r'^contact/$', 'myapp.views.contact'),
    url(r'^login/$', 'django.contrib.auth.views.login'),
]

在导入include()功能时将其更改为以下内容:

urlpatterns = [
    url(r'^$', views.home),
    url(r'^contact/$', views.contact),
    url(r'^login/$', views.login),
]

Your code is

urlpatterns = [
    url(r'^$', 'myapp.views.home'),
    url(r'^contact/$', 'myapp.views.contact'),
    url(r'^login/$', 'django.contrib.auth.views.login'),
]

change it to following as you’re importing include() function :

urlpatterns = [
    url(r'^$', views.home),
    url(r'^contact/$', views.contact),
    url(r'^login/$', views.login),
]

Django URL重定向

问题:Django URL重定向

如何将与其他URL不匹配的流量重定向回首页?

urls.py:

urlpatterns = patterns('',
    url(r'^$', 'macmonster.views.home'),
    #url(r'^macmon_home$', 'macmonster.views.home'),
    url(r'^macmon_output/$', 'macmonster.views.output'),
    url(r'^macmon_about/$', 'macmonster.views.about'),
    url(r'^.*$',  'macmonster.views.home'),
)

就目前而言,最后一个条目将所有“其他”流量发送到主页,但是我想通过HTTP 301302进行重定向。

How can I redirect traffic that doesn’t match any of my other URLs back to the home page?

urls.py:

urlpatterns = patterns('',
    url(r'^$', 'macmonster.views.home'),
    #url(r'^macmon_home$', 'macmonster.views.home'),
    url(r'^macmon_output/$', 'macmonster.views.output'),
    url(r'^macmon_about/$', 'macmonster.views.about'),
    url(r'^.*$',  'macmonster.views.home'),
)

As it stands, the last entry sends all “other” traffic to the home page but I want to redirect via either an HTTP 301 or 302.


回答 0

您可以尝试称为 RedirectView

from django.views.generic.base import RedirectView

urlpatterns = patterns('',
    url(r'^$', 'macmonster.views.home'),
    #url(r'^macmon_home$', 'macmonster.views.home'),
    url(r'^macmon_output/$', 'macmonster.views.output'),
    url(r'^macmon_about/$', 'macmonster.views.about'),
    url(r'^.*$', RedirectView.as_view(url='<url_to_home_view>', permanent=False), name='index')
)

请注意url<url_to_home_view>您实际需要如何指定url。

permanent=False将返回HTTP 302,而permanent=True将返回HTTP 301。

或者,您可以使用 django.shortcuts.redirect

Django 2+版本的更新

在Django 2+中,url()已弃用并替换为re_path()。用法url()与正则表达式完全相同。对于不需要正则表达式的替换,请使用path()

from django.urls import re_path

re_path(r'^.*$', RedirectView.as_view(url='<url_to_home_view>', permanent=False), name='index')

You can try the Class Based View called RedirectView

from django.views.generic.base import RedirectView

urlpatterns = patterns('',
    url(r'^$', 'macmonster.views.home'),
    #url(r'^macmon_home$', 'macmonster.views.home'),
    url(r'^macmon_output/$', 'macmonster.views.output'),
    url(r'^macmon_about/$', 'macmonster.views.about'),
    url(r'^.*$', RedirectView.as_view(url='<url_to_home_view>', permanent=False), name='index')
)

Notice how as url in the <url_to_home_view> you need to actually specify the url.

permanent=False will return HTTP 302, while permanent=True will return HTTP 301.

Alternatively you can use django.shortcuts.redirect

Update for Django 2+ versions

With Django 2+, url() is deprecated and replaced by re_path(). Usage is exactly the same as url() with regular expressions. For replacements without the need of regular expression, use path().

from django.urls import re_path

re_path(r'^.*$', RedirectView.as_view(url='<url_to_home_view>', permanent=False), name='index')

回答 1

在Django 1.8中,这就是我的工作方式。

from django.views.generic.base import RedirectView

url(r'^$', views.comingSoon, name='homepage'),
# whatever urls you might have in here
# make sure the 'catch-all' url is placed last
url(r'^.*$', RedirectView.as_view(pattern_name='homepage', permanent=False))

除了使用之外url,您还可以使用pattern_name,它有点不干,可以确保您更改了网址,也不必更改重定向。

In Django 1.8, this is how I did mine.

from django.views.generic.base import RedirectView

url(r'^$', views.comingSoon, name='homepage'),
# whatever urls you might have in here
# make sure the 'catch-all' url is placed last
url(r'^.*$', RedirectView.as_view(pattern_name='homepage', permanent=False))

Instead of using url, you can use the pattern_name, which is a bit un-DRY, and will ensure you change your url, you don’t have to change the redirect too.


回答 2

如果像我一样坚持使用django 1.2,并且RedirectView不存在,则添加路由映射的另一种以路由为中心的方法是使用:

(r'^match_rules/$', 'django.views.generic.simple.redirect_to', {'url': '/new_url'}),  

您还可以重新路由比赛中的所有内容。这在更改应用程序的文件夹但想要保留书签时非常有用:

(r'^match_folder/(?P<path>.*)', 'django.views.generic.simple.redirect_to', {'url': '/new_folder/%(path)s'}),  

如果您仅尝试修改url路由并且无权访问.htaccess等,则此方法比django.shortcuts.redirect更可取。 .htaccess)。

If you are stuck on django 1.2 like I am and RedirectView doesn’t exist, another route-centric way to add the redirect mapping is using:

(r'^match_rules/$', 'django.views.generic.simple.redirect_to', {'url': '/new_url'}),  

You can also re-route everything on a match. This is useful when changing the folder of an app but wanting to preserve bookmarks:

(r'^match_folder/(?P<path>.*)', 'django.views.generic.simple.redirect_to', {'url': '/new_folder/%(path)s'}),  

This is preferable to django.shortcuts.redirect if you are only trying to modify your url routing and do not have access to .htaccess, etc (I’m on Appengine and app.yaml doesn’t allow url redirection at that level like an .htaccess).


回答 3

做到这一点的另一种方法是使用HttpResponsePermanentRedirect,如下所示:

在view.py

def url_redirect(request):
    return HttpResponsePermanentRedirect("/new_url/")

在url.py中

url(r'^old_url/$', "website.views.url_redirect", name="url-redirect"),

Another way of doing it is using HttpResponsePermanentRedirect like so:

In view.py

def url_redirect(request):
    return HttpResponsePermanentRedirect("/new_url/")

In the url.py

url(r'^old_url/$', "website.views.url_redirect", name="url-redirect"),

回答 4

其他方法也可以,但是您也可以使用旧方法django.shortcut.redirect

下面的代码是从此答案中获取的

在Django 2.x中:

from django.shortcuts import redirect
from django.urls import path, include

urlpatterns = [
    # this example uses named URL 'hola-home' from app named hola
    # for more redirect's usage options: https://docs.djangoproject.com/en/2.1/topics/http/shortcuts/
    path('', lambda request: redirect('hola/', permanent=True)),
    path('hola/', include('hola.urls')),
]

The other methods work fine, but you can also use the good old django.shortcut.redirect.

The code below was taken from this answer.

In Django 2.x:

from django.shortcuts import redirect
from django.urls import path, include

urlpatterns = [
    # this example uses named URL 'hola-home' from app named hola
    # for more redirect's usage options: https://docs.djangoproject.com/en/2.1/topics/http/shortcuts/
    path('', lambda request: redirect('hola/', permanent=True)),
    path('hola/', include('hola.urls')),
]

Django可选的url参数

问题: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 。

I have a Django URL like this:

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

The problem is that I want the project_id parameter to be optional.

I want /project_config/ and /project_config/12345abdce/ to be equally valid URL patterns, so that if project_id is passed, then I can use it.

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


回答 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

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

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:

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要多得多(假设您要将productkwarg 重命名为product_id,只需更改第4行,它就会影响以下网址。

针对Django 1.8及更高版本进行了编辑

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

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

Edited for Django 1.8 and above


回答 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'
),

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.

So it would look like:

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
    ...

使用,path()您还可以使用类型为的可选参数将额外的参数传递给视图。在这种情况下,您的视图不需要该属性的默认值:kwargsdictproject_id

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

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

Django > 2.0 version:

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

# 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 view with the optional argument kwargs that is of type dict. In this case your view would not need a default for the attribute 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.


回答 4

以为我会在答案中加点。

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

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

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

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.

Another way to use regex to accommodate the optional parameter:

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')
]

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

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

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