Django路由详解

时间:2024-01-06 21:38:02

一.路由基础

1.路由url函数:路由自上而下进行匹配;url(正则路径,视图函数内存地址,默认参数,路由别名)

2.路由正则:

规定开始:^  |  规定结束:$

#url(r'index', view.index) 可以匹配:/index/ | /abcindex/ | /indexabc/ | /aindexb/ 均可以匹配

#url(r'^index', view.index) 可以匹配:/index/ | /indexadc/ 均可以匹配

#r'^index$' 只能匹配index,不能匹配index/

#r'^index/$' 可以匹配index和index/(先拿index匹配,如果失败,会自动添加/再次进行匹配)

默认参数:是关键字参数,在视图函数中可以通过关键字参数进行接收

urls.py

#url(r'^index/$', views.index, {'num': 11})

view.py

# def index(request, num):
# pass

路由匹配是否会默认添加/:我们可以通过设置settings.py文件来进行修改

settings.py

# 先把中间件的 'django.middleware.common.CommonMiddleware' 关闭

# 然后新增:

APPEND_SLASH = False

二.有名无名分组

1.无名分组:r'^delete/(\d+)/(\d+)$'

# 路由:url(r'^delete/(\d+)/(\d+)$', views.delete)
#请求路径:/delete/1/2
#视图函数:def delete(request, n1, n2): # n1=1, n2=2

2.有名分组:r'^delete/(?P<id>\d+)/(?P<num>\d+)$'

# 路由:url(r'^delete/(?P<id>\d+)/(?P<num>\d+)$', views.delete)
#请求路径:/delete/1/2
#视图函数:def delete(request, id, num): # id=1, num=2 只能使用id,num来接收参数

注:路由正则不支持有名无名分组混用

三.多app共存的路由分配

1.创建多个app有三种方式:

#1.django-admin startapp app_name

#2.python3 manage.py startapp app_name

#3.Tools工具下的:run manage.py task...

2.在settings.py文件中配置INSTALLED_APPS,添加新建的应用:'app_name.apps.App_nameConfig'。注:app配置的顺序决定了(共同资源冲突下的)查找顺序

3.处理路由冲突

#在主路由中要配置多个app,要对视图函数调用起别名

from app01 import views as app01_views
from app02 import views as app02_views url(r'^app01/test_page/$', app01_views.test_page)
url(r'^app02/test_page/$', app02_views.test_page) # 如果不进行区分的话,它会自上而下进行匹配,最终匹配最后导入的views

四.多app共存时模板冲突问题

方式1:

在对应应用下建立自己的templates文件夹,再在templates下建立与应用名同名的文件夹,模板文件放在应用名同名的文件夹下。

方式2:

在项目根目录下的templates中建立每一个应用名同名的文件夹,每个应用的模板文件放在自己应用名文件夹下

#使用:render(request, 'app_name/test.html')

五.路由分发

目的:分担总路由的代码压力,将每个app的自身路由配置交给app自己的urls.py文件来管理(分文件管理路由)。

步骤:

1.在每一个应用中建立自身的urls.py文件,语法同主路由

2.在主路由中进行分发:

#主路由:
from django.conf.urls import include urlpatterns = [
url(r'^app01/', include('app01.urls')),
url(r'^app02/', include('app02.urls')),
] #注:主路由分发一定不能使用$正则语法,因为后面还要跟子路由的路径 #子路由(app01):
urlpatterns = [
url(r'^login/$', views.login) ]

六.路由别名

'''
1.有些路由会被大量访问(直接访问、间接访问)
2.这些路由可能后期还会发生变化
3.可以给路由设置别名,通过别名访问:<a href="{% url '路由别名' '传入有名无名分组所需参数' %}"></a>
''' # url(r'^index1/(?P<id>\d+)$', views.index, name='index') # 通过别名访问:<a href="{% url 'index' 1 %}"></a>

七.名称空间

'''
主路由:
from django.conf.urls import include
urlpatterns = [
url(r'^app01/', include('app01.urls', namespace='app01')),
url(r'^app02/', include('app02.urls', namespace='app02')),
] app01应用下路由
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^test/', views.test, name='test')
] app02应用下路由
from django.conf.urls import url
from app02 import views
urlpatterns = [
url(r'^test/', views.test, name='test')
] 前端页面反向解析:{% url 'app01:test' %} | {% url 'app02:test' %}
视图函数reverse方法:url = reverse('app01:test') | url = reverse('app02:test')
'''

八.反向解析

'''
from django.shortcuts import reverse
在视图函数中通过reverse方法反向解析出真实的路径 # 1.不带分组:url(r'可能会变的真实路由', 视图函数, name='路由别名')
url = reverse('路由别名') # 2.无名分组:url(r'可能会变的真实路由(带无名分组)', 视图函数, name='路由别名')
url = reverse('路由别名', args=(给无名分组赋值)) # 3.有名分组:url(r'可能会变的真实路由(带有名分组)', 视图函数, name='路由别名')
url = reverse('路由别名', kwargs={给有名分组赋值,key就是有名分组名})

九.2.x新特性

'''
from django.urls import path, re_path # 2.x版本
from django.conf.urls import url # 1.x版本,向下兼容,但不建议使用
urlpatterns = [
path('admin/', admin.site.urls),
] # 1. 2.x版本re_path的使用方式同1.x版本url
# 2. path写的是绝对字符串,请求地址必须与路由地址完全匹配
# 3. path拥有五个转换器:
-- str:匹配除路径分隔符(/)外的字符串,默认
-- int:匹配自然数
-- slug:匹配字母、数字、横杠及下划线组成的字符串
-- uuid:匹配uuid形式的数据
-- path:匹配任何字符串,包括路径分隔符(/) (不能用?)
'''

十.自定义转换器

'''
# 原因:自定义正则匹配目标路径 语法:
1.自定义类
# 匹配11位的185电话
class CVT185phone:
# 匹配过程
regex = '185\d{8}'
def to_python(self, value):
return int(value)
# 反解过程
def to_url(self, value):
return '%11d' % value # 在主路由中
from django.urls import register_converter
from 所在路径 import CVT185phone
register_converter(CVT185phone, 'phone185') path('page/<phone185:msg>/', views.page, name="pages")
'''