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/page<int: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('<username>/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'),
    #...
]

在模板中调用

<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>
{# Or with the year in a template context variable: #}
<ul>
{% for yearvar in year_list %}
<li><a href="{% url 'news-year-archive' yearvar %}">{{ yearvar }} Archive</a></li>
{% endfor %}
</ul>

在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  阅读(219)  评论(0编辑  收藏  举报