django框架——路由层

系列文章目录

第一章 django安装与介绍

第二章 django基础使用


文章目录

  • 系列文章目录
  • 前言
  • 一、路由匹配
    • 1.路由匹配方式
  • 二、无名分组
  • 三、有名分组
  • 四、反向解析
    • 1.使用反向解析获取指定的路由
    • 2.无名分组反向解析
    • 3.有名分组反向解析
  • 五、路由分发
  • 六、名称空间


前言

上一篇文章《django基础使用》,大致演示了基础的django使用方法,接下来的内容将会详细的对路由层进行学习。但在学习之前需要了解django的请求生命周期流程图。

django框架——路由层_第1张图片


一、路由匹配

路由匹配的特点是:

  • 只要匹配上了就会立刻结束执行对应的视图函数
  • url方法的第一个参数其实是一个正则表达式
  • 只要正则表达式能够从用户输入的后缀中匹配到内容就算匹配上了

1.路由匹配方式

django路由匹配再对/xxx没有匹配关系时,会在末尾加上一个斜杠再次匹配
例如:

url(r'^index/', views.index)

针对上面的路由配置,跳转到127.0.0.1/index,第一次匹配不到,会再次发送请求 127.0.0.1/index/ 此时就会配对上,然后根据视图函数返回响应。

这种二次匹配加斜杠的方式可以通过配置来关闭

APPEND_SLASH = False

由于url第一个参数是正则 所以当项目特别大 对应关系特别多的时候要格外的注意是否会出现路由顶替的现象

设置不再url后携带后缀时自动跳转(多用于跳转主页):

url(r"^$", views.index) 

也可以定义一个尾页 用户输入一个没有对应关系的直接返回

url("^.*", views.error)

这样匹配不到关系会自动调用error视图函数,但这样会让一些不应该显示error页面的url也显示项目的error页面,所以不推荐使用。

注意:
路由设置中第一个参数为正则表达式,所以当路由多了之后容易造成一些跳转问题,例如:
127.0.0.1/index/ 对应主页
127.0.0.1/indexasdasdasdasd/ 也会对应到主页,但这样是不符合预期的,所有会使用$对正则进行结尾的限制。


二、无名分组

在用户输入url后,自动匹配关系,然后将设定的部分url作为参数传给视图函数。

无名分组为正则参数中不设置参数名,此时传给视图函数的参数为位置参数。

无名分组路由中的设置方式:

url("^passage/all/(\d*)/$", views.passage) # ()的设置可以是多个
#在无名分组中按照位置传递,第一个传递的为request

此时除了向视图函数传递request以外还传递了一个数字,这个数字表示了第几页。

无名分组视图层中函数的接收方式:

def passage(request, pagination): # 此时pagination中就是对应的页码
#此时为接收一个参数,也可以书写多个形参接收
	.......
#当我们不知道要接收几个参数时可以使用*args来接收
def passage(request, *args):
	...... 

三、有名分组

在用户输入url后,自动匹配关系,然后将设定的部分url作为参数传给视图函数。

有名分组为正则参数中为传递的值设置参数名,此时传给视图函数的参数为关键字参数。

有名分组路由中的设置方式:

url("^passage/all/(?P\d*)/$", views.passage) # ()的设置可以是多个
#在有名分组中按照位置传递,第一个传递的为request,后续参数为关键字参数

此时除了向视图函数传递request以外还传递了一个参数,这个参数表示了第几页。

有名分组视图层中函数的接收方式:

def passage(request, pagination): # 此时pagination中就是对应的页码,此处必须和路由中设置的名字一致
#此时为接收一个参数,也可以书写多个形参接收
	.......
#当我们不知道要接收几个参数时可以使用**kwargs来接收
def passage(request, **kwargs):
	...... 

四、反向解析

页面上有很多a标签链接了其他路由
路由匹配表达式出现了变化,html页面上的地址全部失效
这个时候可以使用反向解析获取对应的路由

1.使用反向解析获取指定的路由

1.在路由层中为指定路由设置name

url(r'^lo/', views.login, name="login_view"),
url(r'^re/', views.register, name="register_view"),

2.在视图层为对应视图函数绑定reverse

from django.shortcuts import reverse
def login(request):
    reverse('login_view')

def register(request):
    reverse('register_view')

3.在对应需要使用路由的前端设置

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>这是主页title>
head>
<body>
    <a href="{% url 'login_view' %}">登录页面a>
    <a href="{% url 'register_view' %}">注册页面a>
body>
html>

2.无名分组反向解析

1.在路由层中为指定路由设置name

url(r"^not/(\d*)/$", views.not_grouping, name="not_view"),

2.在视图层为对应视图函数绑定reverse

from django.shortcuts import reverse
def not_grouping(request, num):
    reverse("not_view", args=(45,))
    return HttpResponse("无名分组参数已发送")

3.在对应需要使用路由的前端设置

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>这是主页title>
head>
<body>
    <a href="{% url 'not_view' 45 %}">文章页面,无名分组,反向解析a>
	<a href="{% url 'not_view' 45 %}">文章页面,无名分组,反向解析a>
body>
html>

3.有名分组反向解析

1.在路由层中为指定路由设置name

url(r"^has/(?P\d*)/$", views.has_grouping, name="has_view"),

2.在视图层为对应视图函数绑定reverse

from django.shortcuts import reverse
def has_grouping(request, num):
    reverse("has_view", args=(65,)) # 绑定方式1 当前端调用反向解析直接传入参数值使用 args来绑定
    reverse("has_view", kwargs={"num":65}) # 绑定方式2 当前端调用反向解析通过关键字参数传入时 使用kwargs来绑定
    #俩种绑定方式在同一个视图函数中只能选一种
    return HttpResponse("有名分组参数已发送")

3.在对应需要使用路由的前端设置

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>这是主页title>
head>
<body>
    <a href="{% url 'has_view' 65 %}">文章页面,有名分组方式1,反向解a>
	<a href="{% url 'has_view' 65 %}">文章页面,有名分组方式1,反向解a>
	{# 上方的方式一,对应reverse按照顺序参数传值时使用#}
	<a href="{% url 'has_view' num=65 %}">文章页面,有名分组方式2,反向a>
	<a href="{% url 'has_view' num=65 %}">文章页面,有名分组方式2,反向解a>
	{# 上方的方式二,对应reverse按照关键字参数传值时使用,特别注意关键字参数编写时不能带上空格#}
body>
html>

五、路由分发

当一个项目特别大时,开发完毕后的路由会非常的大,管理和维护也困难,此时可以将整个项目拆解为多个app容器来各自开发,此时项目文件下的urls.py只需要集成各个app容器的路由即可。

1.在每个app容器中创建自己的urls(最好在各自app容器下创建templates、static)

django框架——路由层_第2张图片

2.对应每个app容器下的路由与视图的编写

3.在项目同名文件中的路由中集成所有app容器中的路由

第一种集成方式,通过导入所有app下的路由,其中传参使用include:

from django.conf.urls import url,include
from django.contrib import admin
from app01 import urls as app01_urls
from app02 import urls as app02_urls

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

第二种集成方式,直接使用注册好的app直接引入路由

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')),
    url(r'^app02/',include('app02.urls')),
]

六、名称空间

当多个app容器中有相同名字的路由被配置时,使用反向解析,路由分发不会分辨其app容器,而是直接使用相同名字中最后一个加载的配置作为解析结果。此时可以使用俩种方式解决该问题。

方法一:
1.在总路由(总路由指项目同名文件下的urls.py)中设置名称空间

url(r'^app01/',include('app01.urls', namespace="app01")),
url(r'^app02/',include('app02.urls', namespace="app02")),

2.在对应app容器对应的路由中设置name

# app01容器下的urls
url(r"^index/", views.index, name="index_view"),

# app02容器下的urls
url(r"^index/", views.index, name="index_view"),

3.在对应需要的视图函数中设置reverse

# app01容器下的views
def index(request):
    reverse("app01:index_view")
    return render(request, "index.html")
# app02容器下的views
def index(request):
    reverse("app02:index_view")
    return render(request, "index1.html")

4.在对应需要使用到反向解析结果的地方使用

<a href="{% url 'app01:login_view' %}">登录页面,反向解析a>
<a href="{% url 'app01:register_view' %}">注册页面,反向解析a>
<a href="{% url 'app01:not_view' 45 %}">文章页面,无名分组,反向解析a>
<a href="{% url 'app01:not_view' 45 %}">文章页面,无名分组,反向解析a>
<a href="{% url 'app01:has_view' 65 %}">文章页面,有名分组方式1,反向解析a>
<a href="{% url 'app01:has_view' 65 %}">文章页面,有名分组方式1,反向解析a>
<a href="{% url 'app01:has_view' num=65 %}">文章页面,有名分组方式2,反向解析a>
<a href="{% url 'app01:has_view' num=65 %}">文章页面,有名分组方式2,反向解析a>

方式二:
只需要确保反向解析的别名在整个项目中不重复即可
可以在别名的前面加上应用名的前缀

# app01容器下的urls
url(r"^index/", views.index, name="app01_index_view"),

# app02容器下的urls
url(r"^index/", views.index, name="app02_index_view"),

你可能感兴趣的