Django之路由层

目录

django请求生命周期流程图

路由匹配

分组命名匹配

无名分组

有名分组

传递额外的参数给视图函数

命名URL 和 URL反向解析

命名URL

URL反向解析--前端

URL反向解析---后端

无名分组反向解析

有名分组反向解析

路由分发

名称空间


django请求生命周期流程图

django的生命周期是:前端请求--->nginx--->uwsgi.--->中间件--->url路由---->view视图--->orm---->拿到数据返回给view---->试图将数据渲染到模版中拿到字符串---->中间件--->uwsgi---->nginx---->前端渲染。

Django之路由层_第1张图片

django请求声明周期流程图
 浏览器基于http协议发送请求>>>进入django的web服务网关接口(wsgiref, tashidjango默认的网关接口,但是并发量很低,所以上线后都会切换为uwsgi以提高并发量, [wsgi是一个协议, 剩下两个都是基于此协议的模块]), 当请求来的时候拆解数据,相应走的时候封装数据, >>>进到django后端[整个django框架]
先经过django中间件,类似于安保系统, 经过筛选后才会将数据传到后边,>>>>进入urls.py 路由层. 在路由曾栗晚成路径匹配, 有了确定路径之后进入视图层,>>>views.py 视图层执行核心业务逻辑,若是全栈项目就需要用到HTML页面,若只写后端接口则不用HTML, >>>>templates文件夹,模板层, >>>>模型层 models.py 去跟数据库做交涉, 模型层链接数据库MySQL.    视图层需要模板的话去模板层拿模板,需要数据的话去模型层拿数据, 根据orm去MySQL里操作, MySQL返回数据,orm将它封装成数据对象,在视图层通过模板语法做一个模板语法渲染, 渲染完之后,直接由视图层返回到中间件,再次经过校验,然后中间件将数据交给网关接口去打包,打包完成之后发送给浏览器,  >>>浏览器接收数据. 

其实在wsgiref之前还有一个nginx,做一个反向代理,提升其并发量,  在整个流程外还有一个缓存数据库,想要请求数据时, 会先去缓存数据库里找, 没有找到的情况下才会去MySQL找. 


学习先从 路由层开始, >>>视图层>>>模板层>>模型层>>>django插件>>>django中间件
 

中间件的作用非常大,可以处理所有的请求内容,中间件其实就是一个类,这个类中一共有5个方法,

分别是

process_request,

process_response,

process_view,

process_exception,

process_render_template,

下面说一下它的运算顺序

Django之路由层_第2张图片

当一个请求,首先从上往下运行这些类中process_request方法,之后进入django的从上往下执行每个类中的process_view方法,在然后就进入我们自定义的view.py文件,如果你的试图中有错误,那就会从下往上执行中间件中的process_exception方法,然后把错误信息在通过process_response中返回给客户端。

process_request:在这个方法中是没有return方法的,如果有那就会执行process_response方法,直接返回给客户端,一般情况下我们是不会在这里返回内容的,除非你有需求,判断发过来的请求过来的内容,如果不是很友好的请求,那么我们直接就可以在这返回,直接卡死,让这个请求直接都进不了我们的django中的内部程序,

process_response:在这个方法中我们必须要有return方法,这样才能一步一步的返回给客户端,当然你也可以写一些东西在response里,在这里写就是会在所有的response里都会有你所添加的内容!

process_view:这个方法中是没有return方法的,如果有那就走process_response方法;

process_exception:在这个方法中是一定要有return方法的,这个方法是专门返回你的错误信息的,我可以在所有的视图函数只要出现错误就会执行这个方法,可以返回一个错误模版信息!

路由匹配

urls.py

from django.conf.urls import url

urlpatterns = [
     url(正则表达式, views视图函数,参数,别名)
]

 参数说明

  • 正则表达式:应该正则表达式字符串
  • views视图函数: 一个可调用对象, 通常为一个视图函数或一个指定视图函数路径的字符串
  • 参数: 可选的要传递给视图函数的默认参数(字典形式)
  • 别名:一个可选择的name参数

注意事项

1. urlpatterns中的元素按照书写顺序从上往下逐一匹配,一旦匹配成功则不再继续

2. 若要从URL中捕获一个值, 只需要在他周围放置一对括号(分组匹配)

3. 不需要添加一个前导的斜杠, 因为每个URL都有, 例如:应该是^articlrs 而不是^/articles

4.每个正则表达式前面的r是可选的, 但是建议加上.

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

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

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

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

分组命名匹配

无名分组

urlpatterns = [
     url(正则表达式, views视图函数,参数,别名)
]

由于第一个参数是正则表达式, 那么就可以给正则的条件加上(),进行分组

urlpatterns = [
    url(r'^test/(\d+)/',views.test)
]

 然后就会报错:test() takes 1 positional argument but 2 were given
说我们给了两个参数

Django之路由层_第3张图片

 views.py

def test(request,a):
    print(a)
    return HttpResponse('你好啊,大漂亮')

再启动

Django之路由层_第4张图片

 无名分组>>>>路由匹配时,如果对正则表达式进行分组,那么会传入除了request参数外,还会分组后匹配到的内容

有名分组

有名分组其实就是对正则表达式分组之后,对分组的内容起了个别名, 同时传入视图函数的时候, 需要特定这个别名的关键字参数来接收

urlpatterns = [
    url(r'^test/(?P\d+)/',views.test)
]

形参中必须要有正则表达式分组起了别名的关键字参数

def test(request, user_id):
    return HttpResponse(f'test url,{user_id}')

无名分组和有名分组不能还在同一个url中混用, 但是可以某种类型重复使用

传递额外的参数给视图函数

URLconfs 具有一个钩子,让你传递一个python字典作为额外的参数传递给视图函数.

django.conf.urls.url() 函数可以接收一个可选的第三个参数,他是一个字典, 表示想要传递给视图函数的额外关键字参数

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

urlpatterns = [
    url(r'^blog/(?P[0-9]{4})/$', views.year_archive, {'foo': 'bar'}),
]

在这个例子中, ,对于/blog/2005/请求,Django 将调用views.year_archive(request, year='2005', foo='bar')

命名URL 和 URL反向解析

命名URL

通过name属性来命名, 注意: 多个URL命名是不可重复的

urlpatterns = [
    url(r'^home/', views.home, name= 'home'),
]

那么给URL命名的场景是什么?

URL反向解析--前端

在urls.py中给某个路径的后缀起了别名之后, 在模板HTML文件中,就可以直接根据{% url'别名''%}直接拿到别名的路径, 而不是手动拼接路径. 这样做的好处在于. 入股哦有修改ur的时候, 就不需要手动到模板文件中一个个修改了

urlpatterns = [
    url(r'^home/', views.home, name= 'home_view'),
  	url(r'^index/', views.index, name= 'index_view'),
]

views.py

from django.shortcuts import render, HttpResponse, redirect

def home(request):
  
  return render(request, 'home.html')

def index(request):
  return HttpResponse('from index')

home.html




    
    Title


    点我!要你好看
    点点点!!!!!


此时修改urls.py

urlpatterns = [
    url(r'^home/', views.home, name= 'home_view'),
  	url(r'^index666/', views.index, name= 'index_view'),
]

会发现反向解析的链接,能够自动解析新的路径!!

URL反向解析---后端

方式一:reverse模块

views.py文件

# 模块导入
from django.shortcuts import redirect, reverse


def func(request):
    _url = reverse('index_view')

    return redirect(f'{_url}')

urls.py

urlpatterns = [
    url(r'^home/', views.home, name= 'home_view'),
  	url(r'^index/', views.index, name= 'index_view'),
  	url(r'^func/', views.func, name= 'func_view'),
]

结果:

“GET /func/ HTTP/1.1” 302 0
“GET /index/ HTTP/1.1” 200 10

方式二:

views.py文件

# 模块导入
from django.shortcuts import redirect


def func(request):
		# 可以直接写别名,也会自动跳转
    return redirect('index_view')

“GET /func/ HTTP/1.1” 302 0
“GET /index/ HTTP/1.1” 200 10

无名分组反向解析

urlpatterns = [
    url(r'^test/(\d+)/',views.test,name='test_view'),
]

def test(request, a):
    res = reverse('index_view')
    print(res)
    return HttpResponse('from test')

当url中对正则表达式进行分组之后,视图函数反向解析出/test/之后,需要继续做后缀的匹配,如果不给一个确切的值的话,那么/test/1/、/test/2/、/test/666/都符合匹配规则,所以视图函数还需要一个参数来匹配/test/之后的参数
后端语法:


def test(request,a):
  	res = reverse('index_view', args=(666,))
    print(res)
    return HttpResponse('from test')

结果展示为:/test/666/

如果无名分组有多个,那么在args括号内一次传入多个即可
前端模板语法:{% url ‘index_view’ 666 %}

有名分组反向解析

urlpatterns = [
    url(r'^test/(?P\d+)/',views.test,name='test_view'),
]

后端语法:

def test(request, user_id):
  	res = reverse('index_view', kwargs={'user_id':666, })
    print(res)
    return HttpResponse('from test')

前端模板语法: {% url 'index_view' user_id=666 %}

路由分发

当一个项目的应用非常多时,在urls.py文件中urlpatterns列表中的路由会非常多,这样会导致非常不好管理路由,这时考虑将一个urls.py文件拆分开,每一个应用单独新建一个urls,py,通过总的路由文件对每个应用的路由文件进行统筹管理

子路由中的路由配置还是按照之前的方式,但是总路由的配置需要改变

导入模块include
 

from django.conf.urls import include, url

urlpatterns = [
   url(r'^admin/', admin.site.urls),
   url(r'^app01/', include('app01.urls')),  # 可以包含其他的URLconfs文件
 	 url(r'^app02/', include('app02.urls')),  # 可以包含其他的URLconfs文件
]

路由匹配时,如果匹配到/app01/会直接到app01.urls.py文件中去继续做路由匹配

名称空间

Django 项目中有两个应用–app01与app02,分别有其各自的urls.py

如果两个项目都有一个url(r’^index/',views.index,name=‘index_view’), 即多个应用出现路由命名冲突的情况!

此时,对index_view这个别名进行反向解析时,能够解析出是属于app01的,还是app02的呢?

直接说结论:当一个项目中有相同的路由命名,只会识别到最后一个起了这个名字的路由,其他的相同命名的路由,无法被反向解析出来

解决办法:在总路由进行路由分发的时候,给每个应用进行命名空间namesapce=的起别名操作
创建多个应用 并去配置文件中注册

INSTALLED_APPS = [
‘app01’,
‘app02’
]

总路由:

from django.conf.urls import include, url

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^app01/', include('app01.urls',namespace='app01')),
    url(r'^app02/', include('app02.urls',namespace='app02')),
]

各自的app的urls.py

urlpatterns = [
    url(r'^index/',view.index,name='index_view')
]

这样在各自的视图函数进行反向解析的时候会有不同的提示

Django之路由层_第5张图片

 其实,该问题的解决方法还可以在给路由重命名时,加上应用的前缀app01_index_view这样可以不使用名称空间,同样达到相同的效果

你可能感兴趣的:(Django,django,python,后端)