django之路由层

时间:2021-09-21 22:45:49

 一 Django中路由的作用

URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL与要为该URL调用的视图函数之间的映射表;你就是以这种方式告诉Django,对于客户端发来的某个URL调用哪一段逻辑代码对应执行

典型的例子:

from django.urls import path

urlpatterns = [
path('articles', views.special),
]
articles这个路由对应着视图函数中special这个方法,浏览器输入这个链接,就会响应到special这个函数来执行

二 简单的路由配置

from django.conf.urls import url

urlpatterns = [
url(正则表达式, views视图函数,参数,别名),
]
  • 第一个参数:正则表达式:一个正则表达式字符串
  • 第二个参数:views视图函数:一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串
  • 第三个参数:参数:可选的要传递给视图函数的默认参数(字典形式)
  • 第四个参数:别名:url的别名,用在前端。一个可选的name参数
from django.urls import path,re_path
from app01 import views urlpatterns = [
  ^以什么开头的意思,/普通字符,$是所以什么结尾的意思。完全匹配
re_path(r'^articles/2003/$', views.special_case_2003),
  任意0-9的数字重复4次
  re_path(r'^articles/[0-9]{4}/$', views.year_archive),
  在视图函数里希望拿到输入的比如1995这个内容。视图函数收的都是字符串。url可以当做路径参数传到视图函数里。
re_path(r'^articles/([0-9]{4})/$', views.year_archive), re_path(r'^articles/([0-9]{4})/[0-9]{2}/$', views.month_archive), re_path(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
    re_path(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]

注意:

  • 若要从URL 中捕获一个值,只需要在它周围放置一对圆括号。
  • 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles
  • 每个正则表达式前面的'r' 是可选的但是建议加上。它告诉Python 这个字符串是“原始的” —— 字符串中任何字符都不应该转义
  • 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

# 是否开启URL访问地址后面不为/跳转至带有/的路径的配置项
APPEND_SLASH=True

Django settings.py配置文件中默认没有 APPEND_SLASH 这个参数,但 Django 默认这个参数为 APPEND_SLASH = True。 其作用就是自动在网址结尾加'/'。

其效果就是:

我们定义了urls.py:

from django.conf.urls import url
from app01 import views urlpatterns = [
url(r'^blog/$', views.blog),
]

访问 http://www.example.com/blog 时,默认将网址自动转换为 http://www.example/com/blog/ 。

如果在settings.py中设置了 APPEND_SLASH=False,此时我们再请求 http://www.example.com/blog 时就会提示找不到页面。

三 有名分组 name groups

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<name>pattern),其中name 是组的名称,pattern 是要匹配的模式。

from app02 import views
from django.conf.urls import url urlpatterns = [
  #无名分组
url(r'^article/\d{4}', views.year) , url(r'^article/(\d{4})$', views.year2),
如果有多个匹配一样的时候,谁放在上面就匹配谁,上面的就会把下面的覆盖了
正则加上括号,就是分组,会把分组的内容作为year2函数的参数传进去
url(r'^article/(\d{4})/(\d{2})$', views.year_month), # 有名分组(就是给分组起个名字,这样定义的好处就是按照关键字参数去传参了,指名道姓的方式)
url(r'^article/(?P<year>\d{4})/(?P<month>\d{2})$', views.year_month_hasname)
]

下面是以上URLconf 使用命名组的重写:

from django.urls import path,re_path

from app01 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.article_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 会更加明晰且不容易产生参数顺序问题的错误 —— 你可以在你的视图函数定义中重新安排参数的顺序。当然,这些好处是以简洁为代价;

第三个参数的应用:

路由:

url(r'^index',views.index,{'name':'zrg'})

视图:

def index(request,name):
return HttpResponse(name)

第四个参数的应用:起别名!

路由:固定写法name=

别名,都是为了防止以后修改的时候发生大量的相关操作。

homepage替换index路径的意思。

路由:

url(r'^index/', views.index,name='homepage'),

template:  前端我们写的是别名,到了后端又会对应过来。

发给前端的一定是已经渲染好的

<form action={% url 'homepage' %} method="post">
<input type="text" name="user">
<input type="password" name="pwd">
<input type="submit" name="submit">
</form>

views:    通过模板语言把浏览器不认识的东西换成认识的东西就是render做的事。

def index(request):
if request.method == 'GET':
return render(request,'login.html')
elif request.method == 'POST':
# 获取前端提交的数据
username = request.POST.get('user')
pwd = request.POST.get('pwd')
# 与数据库的数据进行校验
if username == 'zrg' and pwd == '':
return HttpResponse('登录成功')

四 路由分发

urls.py文件是在全局项目下面。但是如果一个项目功能很多,有多个app。如果多个的都写在urls.py里面会造成干扰冲突,没有解耦。

基于此,我们做路由分发:

1、在每个app里写自己的urls.py

from django.conf.urls import url,include
from app01 import views
urlpatterns = [
url(r'^new/story',views.introduce),
]

app里的视图函数:

from django.shortcuts import render,HttpResponse

# Create your views here.
def introduce(request):
return HttpResponse('路由分发1')

2、全局的urls.py做个指派: include的作用就是映射

from django.conf.urls import url,include
from django.contrib import admin urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^app01/', include('app01.urls')), 以app01开头的去app01里面自己去分发。
]

通过http://127.0.0.1:8000/app01/new/story来访问。

Django1.1版本的分发

from django.conf.urls import url,include
#主urls
from django.urls import path,re_path,include
from app01 import views
from app01 import urls
urlpatterns = [
  # re_path(r'^app01/',include('app01.urls')),#行
  # re_path(r'^app01/&',include('app01.urls')),#不行
  # path('app01/',include('app01.urls')),#行 
  #path('app01/', include(urls)),
]

在app01里创建一个urls

from django.urls import path,re_path
from app01 import views
urlpatterns = [
re_path(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 app01 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>

视图函数中:

from django.shortcuts import render, HttpResponse,redirect,reverse
def url_test(request,year,month):
print(year)
print(month)
url=reverse('test',args=(10,20))
print(url)
return HttpResponse('ok')

总结:1 在html代码里{% url "别名" 参数  参数%}

   2 在视图函数中:

    2.1 url=reverse('test')

    2.2 url=reverse('test',args=(10,20))

当命名你的URL 模式时,请确保使用的名称不会与其它应用中名称冲突。如果你的URL 模式叫做comment,而另外一个应用中也有一个同样的名称,当你在模板中使用这个名称的时候不能保证将插入哪个URL。在URL 名称中加上一个前缀,比如应用的名称,将减少冲突的可能。我们建议使用myapp-comment 而不是comment

六 名称空间

命名空间(英语:Namespace)是表示标识符的可见范围。一个标识符可在多个命名空间中定义,它在不同命名空间中的含义是互不相干的。这样,在一个新的命名空间中可定义任何标识符,它们不会与任何已有的标识符发生冲突,因为已有的定义都处于其它命名空间中。

由于name没有作用域,Django在反解URL时,会在项目全局顺序搜索,当查找到第一个name指定URL时,立即返回
我们在开发项目时,会经常使用name属性反解出URL,当不小心在不同的app的urls中定义相同的name时,可能会导致URL反解错误,为了避免这种事情发生,引入了命名空间。
创建一个app02:python manage.py startapp app02
urls.py
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的视图函数

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

这样都找index,app01和app02找到的都是app02的index

如何处理?在路由分发的时候指定名称空间

总urls.py在路由分发时,指定名称空间

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一样

思考情况如下:

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 解决以上的两个问题。

基本示例

django2.0的re_path和1.0的url一样

思考情况如下:

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> 捕获一个整数变量。若果没有转化器,将匹配任何字符串,当然也包括了 / 字符。
  • 无需添加前导斜杠。

以下是根据 2.0官方文档 而整理的示例分析表:(跟上面url的匹配关系)

aaarticlea/png;base64,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" alt="" width="1560" height="528" />

path转化器

文档原文是Path converters,暂且翻译为转化器。

Django默认支持以下5个转化器:

  • 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 '%04d' % 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.special_case_2003),
path('articles/<yyyy:year>/', views.year_archive),
...
]