django view

View执行步骤

  1. 查找setting.py中的ROOT_URLCONF,跳到对应urls
  • 查找urls.py中的urlpatterns,按顺序依次匹配

  • 返回匹配上的view

  • 如果没匹配上,报错

Example

from django.urls import path

from . import views

urlpatterns = [
path('articles/2003/', views.special_case_2003),
path('articles/int:year/', views.year_archive),
path('articles/int:year/int:month/', views.month_archive),
path('articles/int:year/int:month/slug:slug/', views.article_detail),
]

path converters

str:匹配任何非空字符串,不包括路径分隔符'/'。如果表达式中不包含转换器,这是默认值。

int:匹配0或任何正整数。返回一个int。

slug:匹配任何由ASCII字母或数字以及连字符和下划线组成的段塞字符串。例如,building-your-1st-django-site。

uuid:匹配格式化的UUID。为了防止多个url映射到同一个页面,必须包含破折号和小写字母。例如,0075194d3-6885-417e-a8a8-6c931e272f00返回一个UUID实例。

path:匹配任何非空字符串,包括路径分隔符'/'。这允许您匹配完整的URL路径,而不像使用str那样只匹配URL路径的一个段。

注册custom path converters

对于更复杂的匹配需求,您可以定义自己的路径转换器。

转换器是包含以下内容的类:

  1. regex类属性,如字符串。
  • to_python(self, value)方法,用于将匹配的字符串转换为应该传递给视图函数的类型。如果它不能转换给定的值,就会引发ValueError。

  • to_url(self, value)方法,用于将Python类型转换为URL中使用的字符串。

例子:
converters.py

class FourDigitYearConverter:
regex = '[0-9]{4}'

def to_python(self, value):
return int(value)

def to_url(self, value):
return '%04d' % value

然后,使用register_converter()函数注册

from django.urls import path, register_converter

from . import converters, views

register_converter(converters.FourDigitYearConverter, 'yyyy')

urlpatterns = [
path('articles/2003/', views.special_case_2003),
path('articles/yyyy:year/', views.year_archive),
...
]

re_path converters

正则表达式匹配,语法: (?Ppattern)

Nested arguments

正则表达式允许嵌套参数,Django将解析它们并将它们传递给视图。当执行反转时,Django将尝试填充所有外部捕获的参数,而忽略任何嵌套捕获的参数。考虑下面的URL模式,这些模式可以选择采用页面参数

from django.urls import re_path

urlpatterns = [
re_path(r'^blog/(page-(\d+)/)?$', blog_articles), # bad
re_path(r'^comments/(?:page-(?P<page_number>\d+)/)?$', comments), # good
]

blog/page-2有两个位置参数,page-2和2

comments/page-2有个关键字参数page_number = 2。在本例中,外部参数是一个非捕获参数(?:…)。

URLconf将忽略域名和GET/POST参数

Specifying defaults for view arguments

URLconf

from django.urls import path

from . import views

urlpatterns = [
path('blog/', views.page),
path('blog/pageint:num/', views.page),
]

View (in blog/views.py)

def page(request, num=1):
# Output the appropriate page of blog entries, according to num.
...

性能

urlpatterns中的每个正则表达式都是在第一次访问时编译的。这使得系统非常快

Including other URLconfs

分发路由到其他URLconfs(urls.py文件)

from django.urls import include, path

urlpatterns = [
# ... snip ...
path('community/', include('aggregator.urls')),
path('contact/', include('contact.urls')),
# ... snip ...
]

当遇到inculde时,会截取匹配inculde的字符串,并将截取后的结果返回给下一层URLconfs。

另一种使用方法

old function

from django.urls import path
from . import views

urlpatterns = [
path('<page_slug>-<page_id>/history/', views.history),
path('<page_slug>-<page_id>/edit/', views.edit),
path('<page_slug>-<page_id>/discuss/', views.discuss),
path('<page_slug>-<page_id>/permissions/', views.permissions),
]

include function

from django.urls import include, path
from . import views

urlpatterns = [
path('<page_slug>-<page_id>/', include([
path('history/', views.history),
path('edit/', views.edit),
path('discuss/', views.discuss),
path('permissions/', views.permissions),
])),
]

Captured parameters

inculde()可以传递参数给分发的URLconfs

In settings/urls/main.py

from django.urls import include, path

urlpatterns = [
path('/blog/', include('foo.urls.blog')),
]

In foo/urls/blog.py

from django.urls import path
from . import views

urlpatterns = [
path('', views.blog.index),
path('archive/', views.blog.archive),
]

在views.blog.archive()中可以接受到username的参数

Passing extra options to view functions

URLconfs有一个钩子,可以将额外的参数传递给视图函数,就像Python字典一样。
path()函数可以接受第三个可选的参数,它应该是传递给视图函数的额外关键字参数的字典。

from django.urls import path
from . import views

urlpatterns = [
path('blog/int:year/', views.year_archive, {'foo': 'bar'}),
]

注:如果起名发出冲突,用钩子传递的参数将覆盖path传递的参数值

钩子同时可以用于inculde()方法

main.py

from django.urls import include, path

urlpatterns = [
path('blog/', include('inner'), {'blog_id': 3}),
]

inner.py

from django.urls import path
from mysite import views

urlpatterns = [
path('archive/', views.archive),
path('about/', views.about),
]

它与下列代码功能一致

main.py

from django.urls import include, path
from mysite import views

urlpatterns = [
path('blog/', include('inner')),
]

inner.py

from django.urls import path

urlpatterns = [
path('archive/', views.archive, {'blog_id': 3}),
path('about/', views.about, {'blog_id': 3}),
]

Reverse resolution of URLs

反向解析url

from django.urls import path

from . import views

urlpatterns = [
#...
path('articles/int:year/', views.year_archive, name='news-year-archive'),
#...
]

在模板中调用

2012 Archive
{# Or with the year in a template context variable: #}

在python code中调用

from django.http import HttpResponseRedirect
from django.urls import reverse

def redirect_to_year(request):
# ...
year = 2006
# ...
return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))

使用名称空间

urls.py
from django.urls import include, path

urlpatterns = [
path('author-polls/', include('polls.urls', namespace='author-polls')),
path('publisher-polls/', include('polls.urls', namespace='publisher-polls')),
]

polls/urls.py
from django.urls import path

from . import views

app_name = 'polls'
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('int:pk/', views.DetailView.as_view(), name='detail'),
...
]

in the python code

reverse('polls:index', current_app=self.request.resolver_match.namespace)

in the template

{% url 'polls:index' %}

名称空间和inculde URLconfs

指定inculde URLconfs有两种方式

第一种:设置app_name = ''

polls/urls.py
from django.urls import path

from . import views

app_name = 'polls'
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('int:pk/', views.DetailView.as_view(), name='detail'),
...
]

urls.py
from django.urls import include, path

urlpatterns = [
path('polls/', include('polls.urls')),
]

第二种:嵌套时使用inculde的第二个参数

from django.urls import include, path

from . import views

polls_patterns = ([
path('', views.IndexView.as_view(), name='index'),
path('int:pk/', views.DetailView.as_view(), name='detail'),
], 'polls') # 设置为pools

urlpatterns = [
path('polls/', include(polls_patterns)),
]

posted @ 2018-10-02 12:56  Super-Yan  阅读(238)  评论(0)    收藏  举报