一, 路由基础
URL 配置就像 Django 所支撑的网站的目录. 它的本质是 URL 与要为该 URL 调用的试图函数之间的映射关系表.
以这种方式告诉 Django, 这个 URL 调用的这段代码, 对应哪个 URL 调用的那段代码
1, 基本格式:
- from django.conf.urls import url
- urlpatterns = [
- url(正则表达式, views 视图函数, 参数, 别名),
- ]
注意: Django 2.0 版本中的路由系统已经替换成下面的写法(官方文档):
- from django.urls import path
- urlpatterns = [
- path('articles/2003/', views.special_case_2003),
- path('articles/<int:year>/', views.year_archive),
- path('articles/<int:year>/<int:month>/', views.month_archive),
- path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
- ]
2, 参数说明:
'''
正则表达式: 一个正则表达式字符串
views 试图函数: 一个可调用对象, 通常为一个试图函数或一个指定的试图函数路径的字符串
参数: 可选的要传递给视图函数的默认参数(字典)
别名: 一个可选的 name 参数
'''
3, 正则表达式:
基本配置:
- from django.conf.urls import url
- from . import views
- urlpatterns = [
- url(r'^articles/2003/$', views.special_case_2003),
- url(r'^articles/([0-9]{4})/$', views.year_archive),
- url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
- url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
- ]
注意:
,urlpatterns 中的元素按照书写顺序从上往下逐一匹配, 一旦匹配成功则不再继续
, 若要从 URL 中捕获一个值, 只需要在它周围放置一对圆括号(分组匹配).
, 不需要添加一个前导的反斜杠, 因为每个 URL 都有. 例如, 应该是 ^articles 而不是 ^/articles.
, 每个正则表达式前面的'r' 是可选的但是建议加上.
'''
# 正则路径 视图函数地址 默认关键字参数(了解) 路由别名
# r'^index$' 只能匹配 index, 不能匹配 index/
# r'^index/$' 只能匹配 index/, 能匹配 index(先拿 index 匹配, 如果失败, 会添加 / 再次匹配)
url(r'^index/$', views.index)
url(r'^testkw/$', views.testkw, {'num': 88888}) # def testkw(request, num):
# 路由匹配是否会默认添加 /
# 'django.middleware.common.CommonMiddleware'
# APPEND_SLASH = False
'''
二, 有名无名分组
1, 无名分组
1, 按位置传参
2, 分组后会把分组出来的数据当做位置参数, 传到视图层, 因此视图层需要定义形参
- # 无名分组:/testnoname/10/
- url(r'^testnoname/(\d+)/$', views.testnoname)
- # def testnoname(request, var) # var=10
2, 无名分组
1, 按关键位置传参
2, 有名分组之后, 会把分组出来的数据, 当关键字参数, 传到视图函数, 所以, 视图函数需要定义形参, 形参名字要跟分组的名字对应, 与顺序无关
- # 有名分组:/testname/10/1/
- url(r'^testname/(?P<num>\d+)/(?P<page>\d+)/$', views.testname)
- # def testname(request, page, num) # page=1 num=10
- '''
- # 无名分组:/testnoname/10/
- url(r'^testnoname/(\d+)/$', views.testnoname)
- # def testnoname(request, var) # var=10
- # 有名分组:/testname/10/1/
- url(r'^testname/(?P<num>\d+)/(?P<page>\d+)/$', views.testname)
- # def testname(request, page, num) # page=1 num=10
- # 注: 不能混用
- '''
五, 多 App 共存的路由分配
'''
# 在主路由中药配置多个 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),
'''
六, 多 App 共存时模板冲突问题
'''
方法 1: 在对应应用下建立自己的 templates, 再在 templates 下建立与应用名同名的文件夹, 模板文件放在应用名同名的文件夹下
方法 2: 在项目根目录下的 templates 中建立每一个应用同名的文件夹, 每个应用的模板文件放在自己应用名文件夹下
使用: render(request, 'app_name/test.html')
'''
七, 创建 App 流程
'''
1. python3 manage.py startapp app_name
2. 去 settings 中配置 INSTALLED_APPS, 添加记录:'app_name.apps.App_nameConfig'
# 注: app 配置的顺序决定了 (共同资源冲突下的) 查找顺序
'''
八, 路由分发
- '''
- # 分担总路由的代码压力, 将每个 app 的自身路由配置交给 app 自己的 ulrs.py 来管理(分文件管理路由)
- 1. 在每一个应用中建立自身的 urls.py 文件, 语法同主路由
- 2. 在主路由进行分发
- from django.conf.urls import include
- urlpatterns = [
- url(r'^app01/', include('app01.urls')),
- url(r'^app02/', include('app02.urls')),
- ]
- # 注: 主路由分发一定不能使用 $ 正则语法 (错误 eg: ^app01/$)
- '''
- # 分发路由的路由
- # '''
- # app04/login | app04/register | app04/user/1
- # app05/admin | app05/test
- # '''url(r'^app04/', include('app04.urls', namespace='app04')),
- # 注: 路由分发, 主路由中不能添加 $ 标识结束 (错误 eg: ^app04/$)
- url(r'^app05/', include('app05.urls', namespace='app05'
九, 路由别名
'''
1. 有些路由会被大量访问(直接访问, 间接访问)
2. 这些路由可能后期还会发生变化
3. 可以给路由设置别名, 通过别名访问:<a href="{% url'路由别名''传入有名无名分组所需参数' %}"></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
# 向下兼容, 不建议使用 url, 使用与 url 相同的 re_path
from django.conf.urls import url
urlpatterns = [
path('index/', views.index),
# page/<int:msg>/ page/(?P<msg>(\d+)) # 访问 / page/123/
# path('page/<int:msg>/', views.page),
# path('page/<str:msg>/', views.page),
# path('page/<path:msg>/', views.page),
# path('page/<slug:msg>/', views.page),
path('page/<uuid:msg>/', views.page),
]
# 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")
- '''
来源: http://www.bubuko.com/infodetail-2971793.html