D


玖富娱乐是一家为代理招商,直属主管信息发布为主的资讯网站,同时也兼顾玖富娱乐代理注册登录地址。

Django 系列博客(六)

媒介

本篇博客引见 Django 中的路由掌握局部,一个收集请求起首抵达的就是路由这局部,经由路由与视图层的映照干系再实行响应的代码逻辑并将结果返回给客户端。

Django 中路由的作用

URL 设置装备摆设(URLconf)能够比作是 Django 支撑网站的目次。它的素质是 URL 要为该 URL 滴啊用的视图函数之间的映照表。以这类体式格局通知 Django,关于客户端发来的 URL 要详细挪用视图层的哪段代码。

from django.urls import url
from app import views

urlpatterns = [
    url(r'^$', views.home),
]
# ^$这个路由对应视图函数中的 home 要领,只需浏览器往该网址发送请求,就会响应到这个函数实行。

简朴的路由设置装备摆设

from django.conf.urls import url

urlpatterns = [
    url(正则表达式, views视图函数, 默许参数, 路由别号),
]
  • 正则表达式:一个正则表达式字符串;
  • views 视图函数:一个可挪用对象,一般为一个视图函数或一个指定视图途径的字符串;
  • 默许参数:可选的要通报给视图函数的默许参数(字典情势);
  • 路由别号:一个可选的name 参数。
from django.conf.urls import url
from app import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^article/(d{4})/(d{2})', views.article),
    url(r'^user/(?P<name>[a-z]{3})', views.user_havename),
    url(r'^user/$', views.user),
]

注重:

  • 若要从 URL 中捕捉一个值,只须要在它四周安排一对圆括号;
  • 不须要增加一个前导的反斜杠,因为每一个 url 都有。比方,应当是^articles而不是^/articles
  • 每一个正则表达式前面的r是可选的,然则发起加上,透露表现这是个原生字符串,字符串中的任何字符都不应当转义。
  • urlpatterns 中的元素依照誊写递次从上往下一一婚配正则表达式,一旦婚配胜利则不再继承。
一些请求的例子:

/articles/2005/03/ 请求将婚配列表中的第三个形式。Django 将挪用函数views.month_archive(request, '2005', '03')。
/articles/2005/3/ 不婚配任何URL 形式,因为列表中的第三个形式请求月份应当是两个数字。
/articles/2003/ 将婚配列表中的第一个形式不是第二个,因为形式按递次婚配,第一个会起首测试是不是婚配。请像如许自在插进去一些特别的状况来探测婚配的序次。
/articles/2003 不婚配任何一个形式,因为每一个形式请求URL 以一个反斜线末端。
/articles/2003/03/03/ 将婚配末了一个形式。Django 将挪用函数views.article_detail(request, '2003', '03', '03')。

APPEND_SLASH

该参数的作用是会在接见衔接的时刻,若是衔接没有加斜杠,会自动加上。能够在global_settings.py中修正。

项目的 settings 中没有改设置装备摆设的选项,一个项目会有两个 settings。

结果:

from django.conf.urls import url
from app_01 import views

urlpatterns = [
    url(r'^blog/$', views.blog),
]

当我们接见http://www.example.com/blog时,默许将网址自动替换成http://www.example.com/blog/。若是将该设置装备摆设值设为false,此时在向该网址发送请求时就会提醒找不到页面。

分组

当我们须要捕捉 url 中的参数并要通报给视图函数时,有两种捕捉体式格局:无名分组和著名分组。无名分组就是该值没有变量标识,传值的时刻接纳地位参数通报;著名分组就是给捕捉的值赋值一个变量,如许就能够经由过程关键字参数传值了。

无名分组

# urls.py文件
from django.conf.urls import url
from app_01 import views

urlpatterns = [
    url(r'^article/(d{4})/(d{2})', views.article),
]
# views.py文件
from django.shortcuts import HttpResponse

def article(reques, year, month):
    return HttpResponse('您要检察%s 年%s 月的文章' %(year, month))

经由过程圆括号捕捉年份和月份,然后经由过程地位参数通报给 year 和 month 变量,接着在 views 函数中运用。

著名分组

import re
ret=re.search('(?P<year>[0-9]{4})/([0-9]{2})','2012/12')
print(ret.group())
print(ret.group(1))
print(ret.group(2))
print(ret.group('year'))

这些示例运用简朴的、没有定名的正则表达式组(经由过程圆括号)来捕捉 URL 中的值并以地位参数通报给视图。在更高等的用法中,能够运用定名的正则表达式组来捕捉 URL 中的值并以关键子参数通报给视图函数。

在python 正则表达式中,定名著名分组的语法时(P<变量名>pattern),个中变量名是分组的标识符,pattern 是要婚配的正则表达式。下面是上面 URLconf 运用著名分组的重写:

from django.urls import path, re_path
from app_01 import views

urlpatterns = [
    re_path(r'^articles/2003/$', views.special_case_2003),
    re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
    re_path(r'^articles/(?P<year[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
    re_path(r'^articles/(?P<year[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.archive_detail),
]
# 捕捉到的数据都是 str 范例
# 视图函数里能够指定默许值
url('blog/$', views.blog),
url('blog/?(?P<num>[0-9]{1})', views.blog),
def blog(request, num=1):
    print(num)
    return HttpResponse('ok')

这个完成与前面的示例完全雷同,只要一个纤细的差异:捕捉的值作为关键字参数而不是地位参数通报给视图函数。比方:

/articles/2005/03/ 请求将挪用views.month_archive(request, year='2005', month='03')函数,而不是views.month_archive(request, '2005', '03')。
    /articles/2003/03/03/ 请求将挪用函数views.article_detail(request, year='2003', month='03', day='03')。

在现实运用中,这意味你的 URLconf 会越发清楚且不轻易发作参数递次题目的毛病,能够在视图函数界说中重新安排参数的递次。

路由分发

实在和项目名雷同的文件夹下面的urls.py文件是全部项目的根路由:

这是全部项目的根路由,一切向该项目发送的衔接请求,起首须要从该路由设置装备摆设内里过滤,若是只要一个运用,或许路由设置装备摆设未几一个根路由就足够了,但当 app 多起来以后照样运用一个根路由设置装备摆设会形成路由杂沓,所以有了路由分发,好比这是发往app_01运用的衔接,那末在根路由中举行路由分发,把衔接转向app_01中的路由中举行处置惩罚,这就是路由分发。

# 根路由设置装备摆设
from django.conf.urls import url, include
from app_01 import views
from app_01 import urls

urlpatterns = [
    url(r'^app_01/', include('app_01.urls')), # 注重前面的正则表达式背面不克不及加$
    url(r'^app_01/', include(urls)),
]
# 运用路由设置装备摆设
from django.conf.urls import url
from app_01 import views

urlpatterns = [
    url(r'^test/(?P<year>[0-9]{2})/$', views.url_test),
]

反向剖析

在运用 Django 项目时,一个罕见的需求是取得 URL 的终究情势,以用于嵌入到天生的内容中(视图中和显现给用户的 URL 等)或许用于处置惩罚服务器端的导航(重定向等)。人们猛烈愿望不要硬编码这些 URL(费时辛苦、弗成扩大且易发作毛病)或许设想一种与 URLconf 毫不相关的特地的 URL 天生机制,因为如许轻易致使肯定程度上发作逾期的 URL。

在须要 URL 的处所,关于分歧层级,Django 供应分歧的对象用于 URL 反查:

  • 在模板中:运用 url 模板标签;
  • 在 python 代码中:运用from django.urls import reverse
# urls.py文件
from django.urls import path, re_path
from app_01 import views

urlpatterns = [
    re_path(r'^test/(?P<year>[0-9]{2})/(P?<month>[0-9]{2})/$', views.url_test, name='test'),
]
<!-- html文件 -->
<a href="{% url 'test' 10 23 %}">哈哈</a>
# views.py文件
from django.shortcuts import render, HttpResponse, redirect, reverse

def url_test(request, year, month):
    url = reverse('test', args=(10, 20))
    return HttpResponse('ok')

总结:

-玖富娱乐是一家为代理招商,直属主管信息发布为主的资讯网站,同时也兼顾玖富娱乐代理注册登录地址。-
  • 在 html 代码内里运用{% url '别号' 参数 参数... %}
  • 在视图函数中:
    • url = reverse('test')
    • url = reverse('test', args=(10, 20))

当定名 URL 形式时,要确保运用的称号不会与其他运用中的称号发作争执。若是你的 URL 形式叫做 comment,而别的一个运用中也有一个一样的名字,当你在模板中运用这个称号的时刻不克不及包管将插进去哪一个 URL。在 URL 称号加上一个前缀,好比运用的称号,将会削减争执的能够。发起运用myapp-comment

称号空间

定名空间(namespace)是透露表现标识符的可见局限。一个标识符可在多个定名空间中界说,它在分歧定名空间中的寄义是互不相关的。如许在一个新的定名空间中能够界说任何标识符,它们不会与任何已有的标识符发作争执,因为已有的界说处于其他的定名空间中。

因为name没有作用域,Django 在返解 URL 时,会在项目的全局途径中按递次搜索,当查找到第一个name指定的 URL 时,马上返回。

在开辟项目时,会常常运用name属性反解出 URL,当不小心在分歧的 app 的 urls 中界说雷同的name时,能够会致使 URL 反解毛病,为了制止发作引入了定名空间。

建立 app01和 app02

python manage.py startapp app01

python manage.py startapp app02

根路由

from django.urls import path,re_path,include

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

app01的 urls.py

from django.urls import path,re_path
from app01 import views

urlpatterns = [
    re_path(r'index/',views.index,name='index'),
]

app02的 urls.py

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

urlpatterns = [
    re_path(r'index/', views.index,name='index'),
]

app01的视图

def index(request):
    url=reverse('index')
    print(url)
    return HttpResponse('index app01')

app02的视图

def index(request):
    url=reverse('index')
    print(url)
    return HttpResponse('index app02')

如许都找index.html,app01和 app02找到的都是app02的 index。怎样处置惩罚?在路由分发的时刻指定称号空间。根路由在路由分发是,指定称号空间。

# 一
path('app01/', include(('app01.urls','app01'))),
path('app02/', include(('app02.urls','app02')))

# 二
url(r'app01/',include('app01.urls',namespace='app01')),
url(r'app02/',include('app02.urls',namespace='app02'))

# 三
url(r'app01/',include(('app01.urls','app01'))),
url(r'app02/',include(('app02.urls','app02')))

在视图函数反向剖析的时刻,指定称号空间:

url=reverse('app02:index')
print(url)
url2=reverse('app01:index')
print(url2)

在模板内里也是用响应的称号空间名:

<a href="{% url 'app02:index'%}">哈哈</a>

Django2.0版的 path

Django2.0的re_path和1.0的url一样。2.0多了个path

思索状况以下:

urlpatterns = [  
    re_path('articles/(?P<year>[0-9]{4})/', year_archive),  
    re_path('article/(?P<article_id>[a-zA-Z0-9] )/detail/', detail_view),  
    re_path('articles/(?P<article_id>[a-zA-Z0-9] )/edit/', edit_view),  
    re_path('articles/(?P<article_id>[a-zA-Z0-9] )/delete/', delete_view),  
]

斟酌下如许的两个题目:

第一个题目,函数 year_archive 中year参数是字符串范例的,因而须要先转化为整数范例的变量值,固然year=int(year) 不会有诸如如TypeError或许ValueError的非常。那末有无一种要领,在url中,使得这一转化步调能够由Django自动完成?

第二个题目,三个路由中article_id都是一样的正则表达式,然则你须要写三遍,当以后article_id划定规矩转变后,须要同时修正三处代码,那末有无一种要领,只需修正一处便可?

在Django2.0中,能够运用 path 处理以上的两个题目。

基础示例

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>/', views.article_detail),  
  # path才支撑,re_path不支撑
  path('order/<int:year>',views.order),
]

基础划定规矩:

  • 运用尖括号(<>)从 url中捕捉值;
  • 捕捉值中能够包罗一个转化器范例(converter type),好比运用<int:name>捕捉一个整数变量。若是没有转化器,将婚配任何字符串,也包罗/字符。
  • 无需增加前导斜杠

以上是示例,离别和上面的基础示例对应:

path 转换器

  • str:婚配除途径分隔符(/)以外的非空字符串,这是默许的情势;
  • int:婚配正整数,包罗0;
  • slug:婚配字母、数字、横杠和下划线构成的字符串;
  • uuid:婚配格式化的uuid,如075194d3-6885-417e-a8a8-6c931e272f00。
  • path: 婚配任何非空字符,包罗了途径分隔符(/)

注册自界说转化器

关于一些庞杂或许复用的须要,能够界说本身的转化器。转化器是一个类或接口,它的请求有三点:

  • regex类属性,字符串范例;
  • to_python(self, value)要领,value 是由类属性 regex 所婚配到的字符串,返回详细的 python 变量值,以供 Django 通报到对应的视图函数中;
  • to_url(self, value)要领,和to_python相反,value 是一个详细的 python 变量值,返回其字符串,一般用于 url 反向援用。

示例

class FourDigitYearConverter:
    regex = '[0-9]{4}'
    
    def to_python(self, value):
        return int(value)
    
    def to_url(self, value):
        return 'd' % value

运用register_converter将其注册到 URL 设置装备摆设中:

from django.urls import register_converter, path
from . import converters, views

register_converter(converters.FourDigitYearConverter, 'yyyy')

urlpatterns = [
    path('articles/2003/', views.spwcial_case_2003),
    path('articles/<yyyy:year>/', views.year_archive),
]
-玖富娱乐是一家为代理招商,直属主管信息发布为主的资讯网站,同时也兼顾玖富娱乐代理注册登录地址。