Django 路由层

参考文档:https://zhuanlan.zhihu.com/p/151366705

Django URL路由系统是什么

按照WSGI原理代码,所有请求都交给一个app处理,如何做到不同请求对应不同的处理?
最简单的方式就是,进入app后,不同的URL做不同的处理。也就是,建立URL和处理函数之间的映射。

路由:根据访问的路径Path不同调度不同的处理函数。可以对路径Path采用模式匹配。
Django 3.x使用path、re_path定义,这和2.x略有区别

简而言之,路由系统就是URL路径和视图函数的一个对应关系,也可以称为转发器。

路由配置

path参考:https://docs.djangoproject.com/en/3.2/topics/http/urls/#example

主目录中的urls.py是路径匹配的入口,它定义在 settings.py 中 ROOT_URLCONF = 'devops.urls' 约定,称主目录中的路由配置文件urls.py为 主路由 或 一级路由

URL路由系统格式:

# devops/urls.py
urlpatterns = [
    path(regex, view, kwargs=None, name=None),
]

urlpatterns:一个列表,每一个path()函数是一个元素,对应一个视图
参数:
• regex:一个字符串或者正则表达式,匹配URL,类似于Nginx中的location
• view:对应一个函数视图或者类视图(as_view()的结果),必须返回一个HttpResponse对象,Django将这个对象转换成一个HTTP响应,类似于Nginx location中配置的proxy_pass
• kwargs:可选,字典形式数据传递给对应视图
• name:可选,URL名称,URL路径别名,一般用于前端试图模板中

路由分发

项目目录下的urls.py叫 根路由/主路由文件 应用目录下的urls.py叫 二级路由文件

如果所有路由都定义在主路由文件中,太乱太臃肿,解决的办法就是二级路由/路由分发,即路由到应用的路有文件。但是脚手架建立的应用文件中缺少urls.py,手动在应用目录建立一个。
URL路由分发好处:urls配置解耦,方便管理

示例

# 1.主路由文件
# devops/urls.py
from django.contrib import admin
from django.urls import path, include
from myapp import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/', views.index),
    # include函数,指向二级路由文件/应用路由文件
    path('myapp/', include('myapp.urls')),
]
# 2.应用路由文件
# 在myapp目录下新建urls.py
from django.urls import path
from .views import index, test_index

urlpatterns = [
    path("", index),    # 二级路由包含前缀myapp/,对应URL是/myapp/
    path("hello", test_index),  #二级路由包含前缀myapp/,对应URL是/myapp/hello
]
# 3.在myapp/view.py中增加test_index视图函数
from django.shortcuts import render
from django.http import HttpResponse


def index(request):
    return HttpResponse("hello,world")


def test_index(request):
    return HttpResponse("hello,test_index")

# 访问 http://127.0.0.1:8000/myapp, http://127.0.0.1:8000/myapp/hello

正则表达式匹配/分组

URL路径也可以使用正则表达式匹配,re_path()替代path()
re_path支持正则表达式,参考: https://docs.djangoproject.com/en/3.2/topics/http/urls/#using-regular-expressions

无名分组/普通分组


"""
devops/urls.py 主路由文件配置
"""
from django.contrib import admin
from django.urls import path, include, re_path
from myapp import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/', views.index),
    path('myapp/', include('myapp.urls')),
    re_path('articles/2020/$', views.specified_2020),
    # 下述正则表达式会匹配url地址的路径部分为:article/数字/,匹配成功的分组部分会以位置参数的形式传给视图函数,有几个分组就传几个位置参数
    re_path('^articles/([0-9]{4})/$', views.year_archive),
    re_path('^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
    re_path('^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]

"""
myapp/view.py 视图函数
"""
from django.http import HttpResponse


def index(request):
    return HttpResponse("hello,world")


def test_index(request):
    return HttpResponse("hello,test_index")


def specified_2020(request):
    return HttpResponse("指定2020年 文章列表")

# 需要额外增加形参用于接收传递过来的分组数据
def year_archive(request, year):
    return HttpResponse("%s年 文章列表" % year)


def month_archive(request, year, month):
    return HttpResponse("%s年/%s月 文章列表" % (year, month))


def article_detail(request, year, month, id):
    return HttpResponse("%s年/%s月 文章ID: %s" % (year, month, id))

有名分组/命名分组
当我们对分组命名后,就会按照key=value的关键字参数形式为视图函数传参
url.py

from django.contrib import admin
from django.urls import path,re_path
from myapp import views

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

    # 该正则会匹配url地址的路径部分为:article/数字/,匹配成功的分组部分会以关键字参数(article_id=匹配成功的数字)的形式传给视图函数,有几个有名分组就会传几个关键字参数
    # 需要强调一点是:视图函数得到的值均为字符串类型
    re_path(r'^article/(?P<article_id>\d+)/$',views.article), 
]

views.py文件

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

# 需要额外增加一个形参,形参名必须为article_id
def article(request,article_id):
    return HttpResponse('id为 %s 的文章内容...' % article_id)

测试

python manage.py runserver 8001 # 在浏览器输入:http://127.0.0.1:8001/article/3/ 会看到: id为 3 的文章内容...

总结

普通分组和命名分组都是为了获取路径中的参数,并传递给视图函数,区别在于普通分组是以位置参数的形式传递,命名分组是以关键字参数的形式传递。
普通分组和有名分组不要混合使用

反向解析

名称空间

posted @ 2025-09-23 17:42  城市炊烟  阅读(17)  评论(0)    收藏  举报