Django框架路由详解

在开始前需要先弄清楚几个概念

  • 路由
  • 路由表
  • 路由分发

django 路由介绍

在介绍 django 的路由之前,你知道什么是路由吗?

路由

路由(routing)就是通过互联的网络把信息从源地址传输到目的地址的活动。路由发生在 OSI 网络参考模型中的第三层即网络层

来自维基百科

就像当你用地图的时候,你输入当前地址,输入目的地址,然后就会出来一条路径信息,告诉你应该怎么走,对于 django 同样也是如此,当我们在浏览器上输入一段网址时,这个网址就是我们的目的地,而源地址就是我们的浏览器。

以上就是关于路由的介绍,只需要知道:源、目标

路由表

路由表是一个存储在路由器或者联网计算机中的电子表格(文件)或类数据库。路由表存储着指向特定网络地址的路径
说白了路由表存储了很多条的路由信息,就比如说去一个陌生城市,买了一张地铁线路图,这张图就好比一张路由表,这张图里记录了很多的错综复杂的地铁线路信息,比如在北京,我们现在互联网聚集地:西二旗,我们想去故宫,那么我们就可以查阅这张图,这样我们就知道了线路,又比如你今天去故宫,明天去中关村,后天去北京南站,总之不管你去哪,我们都可以在这张图里找到我们的出行线路,这张图就是我们的路由表

路由分发

还是坐地铁啊,当我们在地铁线路图(路由表)里找到了我们的线路信息(路由)之后,我们乘坐地铁来到了这个地铁站,但是作为一个正常人,你想想我们去地铁站干毛线,我们坐地铁的最终目的不就是去一个确切的地方吗,比如我们早晨上班,同样都是坐到某站就下次,但是大家的最终目的地都不一样,有的人去 A 公司,有的去 B 公司,有的人去 A 酒吧,有的去 B 保健,每一个人都是一条路由,而每个人去的最终目的地都是路由分发的结果

简而言之一句话就是:通过路由表查找路由信息,根据路由信息最终达到目的地。

django 路由

django 中也是这个道理,django 里存放着一张路由表,当请求经过这个路由表时,根据请求内容找到路由信息,随后进行分发,分发到最终一个一个的函数中,函数最终才是我们的目的地。

django 的路由表实际上是保存到一个列表里的: urlpatterns, 如下所示

# urls.py

from django.contrib import admin
from django.urls import path

urlpatterns = [
    path('admin/', admin.site.urls),
]

下面将结合示例来介绍

在介绍之前,首先创建一个 django 项目

# 创建一个项目
django-admin startproject mysite2

django 路由示例

最简单的一个路由

请求/articles/2021/11来获取某一天的文章信息

  1. 首先创建一个视图函数

这里用到了一个HttpResponse类,用于对返回给浏览器的数据进行封装,返回一个HttpResponse对象

# 没有此文件,就创建下
# mysite2/views.py

# 导一下HttpResponse包
from django.http import HttpResponse

def article_detail(request):
    return HttpResponse("文章信息")
  1. 建立路由映射

这里模拟一个文章归档目录的请求,所有的文章归档情况都在articles/目录下,然后用时间进行区分,这里把时间写死,同时思考下如果我们要看 2021 年所有月份的文章咋办

from django.contrib import admin
from django.urls import path
from .views import article_detail

urlpatterns = [
    path('admin/', admin.site.urls),
    path('articles/2021/11/', article_detail)
]
  1. 访问测试

将我们的 django 项目运行起来

python3 manage.py runserver

浏览器访问测试

http://127.0.0.1:8000/articles/2021/11/
Django框架路由详解

这样一整套流程下来,我们已经大致了解了下流量的访问顺序,大致就是:

  1. 浏览器发起请求
  2. django 接收请求
  3. 进入 urls.py 中
  4. 查找 urlpatterns 里的路由
  5. 找到一条路由,并进入到相应的视图函数中
  6. 进入视图函数,开始处理请求,并构造一个响应,返回给浏览器

正则匹配路由

上面的案例中有一个问题就是,当我们请求一整年的月份信息时,我们要设置一堆路由,大概就是下面这种

urlpatterns = [
    path('articles/2021/1', article_detail01),
    path('articles/2021/2', article_detail02),
    path('articles/2021/3', article_detail03),
    path('articles/2021/4', article_detail04)
]

这样倒是可以,当我们肯定不能这么干,我们可以通过使用 django 的re_path方法来通过设置一些正则来进去匹配,就像下面这样的:

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

urlpatterns = [
    re_path('articles/(\d{4})/(\d{1,2})', article_detail)
]

注意:正则一定要写到小括号()里,表示捕获组的意思

那这样我们修改下视图函数

def article_detail(request, year, month):
    print(year, month)
    return HttpResponse(f"{year}年{month}月")

再次运行下项目,访问测试:

http://127.0.0.1:8000/articles/2021/10/

有名分组路由

有名分组是对上面的一个简单补充,很简单,就是通过设置组名,在传参的时候,可以指定组名进行传承

修改路由信息

# 修改路由
urlpatterns = [
    re_path('articles/(?P<year>\d{4})/(?P<month>\d{1,2})', article_detail)
]

视图函数不需要修改,但是需要注意,视图函数中的关键字参数名称不能边,必须和我们设置的组名保持一致才行。

路由分发

通过上面的示例,我们想象一下,加入有几百条路由信息,那么是不是urlpatterns这个列表会非常的长,维护起来是不是特别费劲,再结合我们一开始讲的那个坐地铁的例子,我们可不可以先到站,这个人到西二旗站,另一个人到中关村站,我们先把请求进行分组,不同的请求进入到不同的组中。

django 里肯定可以这样做,通过创建不同功能的应用,然后把请求分发到不同的应用里,最后在将不同的应用请求映射到不同的视图函数中,这样不仅可以解耦,维护起来也会清晰

创建一个应用

创建一个 user 应用,这个应用简单输出一下看下效果

python3 manage.py startapp user

创建好应用之后,我们需要创建urls.py的文件,然后设置好我们的子路由的一些信息.

进入到user这个应用中

# user/urls.py

from django.urls import path
from .views import user_list

urlpatterns = [
    path('list/', user_list)
]

user应用的视图函数

from django.shortcuts import render
from django.http import HttpResponse


# Create your views here.

def user_list(request):
    return HttpResponse("this is a user app")

然后最后我们设置下总路由,回到mysite2下的urls.py

from django.contrib import admin
from django.urls import path, re_path, include
from .views import article_detail

urlpatterns = [
    path('admin/', admin.site.urls),
    # path('articles/2021/11/', article_detail),
    re_path('articles/(?P<year>\d{4})/(?P<month>\d{1,2})', article_detail),
    path('user/', include('user.urls'))
]

这里我们创建的应用名为:user,然后我们这里设置的路由为user/,意思是所有是user/开头的请求都会被转发到user.urls中,而如何转发,则用include方法就可以了。

我们再去访问测试,结果如下

Django框架路由详解

路由转换器

对于一些更复杂的匹配需求,django 提供了自定义转换器。
首先转换器是一个类,我们需要定义一个类,类中包含以下内容:

  • regex类属性,定义一个正则表达式
  • to_python(self, value)方法,将 url 中的值进行转换,然后传递给视图函数
  • to_url(self, value)方法,在做 URL 反转时,将传递进来的参数转换后拼接成一个正确的 url

url 反转就是,一般我们都是通过 url 来访问视图函数,现在我们知道视图函数,想找到这个视图函数对应的 url,这个就叫反转 url

接下来我们创建一个应用,然后在这个应用里定义一个打印手机号的视图函数

  1. 启动一个应用
python3 manage.py startapp mobile

2)设置主路由

from django.contrib import admin
from django.urls import path, re_path, include
from .views import article_detail

urlpatterns = [
    path('admin/', admin.site.urls),
    # path('articles/2021/11/', article_detail),
    re_path('articles/(?P<year>\d{4})/(?P<month>\d{1,2})', article_detail),
    path('user/', include('user.urls')),
    path('mobile/', include('mobile.urls'))  # 指向新创建的mobile应用
]
  1. 定义一个转换器

我们直接在新创建的 mobile 应用中的urls.py里定义

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


class MobileConverter:
    # 定义正则表达式
    regex = '1[3-9]{2}\d{8}'

    def to_python(self, value):
        return int(value)


register_converter(MobileConverter, 'mobile')

urlpatterns = [
    path('info/<mobile:mobile_number>', print_mobile)
]

注意这里<mobile:mobile_number>这俩的区别,mobile这个是我们定义的转换器中传入参数的一个名称,而后面的mobile_number是我们要传给视图函数的参数。

  1. 创建视图函数
from django.shortcuts import render
from django.http import HttpResponse


# Create your views here.
def print_mobile(request, mobile_number):
    return HttpResponse(f"Your mobile number is {mobile_number}")

访问测试:

Django框架路由详解

如果我们试着输一个 12 位的手机号,这里就会直接报错

Django框架路由详解

反向解析

反向解析的一个好处就是随着项目功能的增加,路由也随之增多,当某些 url 频繁更改时,那么随之而来的就是视图层、模板层可能都要随之改动,这样非常不利于维护,所以我们通过设置反向解析,当路由层的 url 发生变化时,视图层和模板层可以动态的进行反向解析,从而找到更改后的 url,通过这样的方式,我们可以免去修改 url 的操作。

下面只以视图层为例

  1. 首先给路由设置一个 name
from django.contrib import admin
from django.urls import path, re_path, include
from .views import index, login

urlpatterns = [
    path('index/', index, name="index"),
    path('login/', login)
]

这里我们创建了一个指向 index 的路由,并给这个路由设置了一个名称, 同时为了简单的测试,又创建了一个 login 的路由,在访问 login 的时候,会进行重定向,最终会指向首页

  1. 创建视图函数
from django.shortcuts import HttpResponse, redirect, reverse


def index(request):
    return HttpResponse("This is a index")


def login(request):
    return redirect(reverse("index"))
  1. 访问测试

这里访问 login 即可,正常来说会 302 到 index 上,我们看下效果

Django框架路由详解

接下来修改 index 的路由

urlpatterns = [
    path('indexs/', index, name="index"),
    path('login/', login)
]

再次访问

Django框架路由详解

原创文章,作者:Rosmontics,如若转载,请注明出处:https://rosmontis.com/archives/189

(0)
上一篇 2022年5月7日
下一篇 2022年5月7日
alt

相关推荐

发表回复

登录后才能评论
TG通知群
小程序
小程序
分享本页
返回顶部