0.路由系统
本质上:URL和函数的对应关系。
1.传统的路由
示例:包含一个apps,内含两个app device和asserts
路由分发方式为通过主路由找分app的路由,在app的路由内找本app的views
主路由urls
from django.urls import path,include
urlpatterns = [
path('device/',include("apps.device.urls")),
path('asserts/',include("apps.asserts.urls")),
# 注意不要在device前加/,那样就出问题了
]
device 的urls
需要在文件内定义app_name
from django.urls import path,re_path
from apps.device import views
urlpatterns = [
path('home/',views.home),
path('web/',views.web),
]
app_name="device"
device内的views
from django.shortcuts import render,HttpResponse
def home(request):
return HttpResponse("home page")
def web(request):
return HttpResponse("web page")
这里不用定义app_name
2. 路由分发
假如:200个功能。
inlucde + app(一般),将功能拆分不到不同的app中。 但是要定义每一个app的app_name到urls内
手动路由分发,可以与app无关。 可以不定义app_name
path('user/add/', views.login),
path('user/delete/', views.login),
path('user/edit/', views.login),
path('user/list/', views.login),
path('user/', ([
path('add/', views.login),
path('delete/', views.login), # /user/delete/
path('edit/', views.login),
path('list/', views.login),
], None, None)),
纯粹帮助提取功能的URL,防止重复编写。
路由分发的本质:
-
URL对应函数
path('user/add/', views.login),
-
URL对应元组
path('user/add/', (元素,appname元素,namespance元素) ),
path('user/add/', include("apps.api.urls") ), # 查看include 也是元组 path('user/add/', ([],None,None) ),
小结
-
include或手动元组列表,本质相同。
-
应用场景和意义,想要把一些URL前缀提取出来。
path('user/add/', views.login), path('user/delete/', views.login), path('user/edit/', views.login), path('user/list/', views.login), path('user/', ([ path('add/', views.login), path('delete/', views.login), # /user/delete/ path('edit/', views.login), path('list/', views.login), ], None, None)), path('users', include(([ path('add/', views.login), path('delete/', views.login), # /user/delete/ path('edit/', views.login), path('list/', views.login), ], None))), include("apps.api.urls") # 一般是每个app中urls urlpatterns = [ ]
3. name
name是可以用于单APP的情况,如果是多APP的话,需要为每个app添加单独的namespace
给一个路由起个名字 + 根据名字反向生成URL。
urlpatterns = [
path('login/', views.login),
]
# 很多功能,很多URL
urlpatterns = [
path('login/', views.login, name="v1"),
path('auth/', views.auth, name="v2"),
]
有了名字后,以后一般有两处会用到:
-
在视图函数中生成URL
from django.urls import reverse url = reverse("v2") # /auth/ url = reverse("v1") # /login/
-
HTML模板,页面上有一个a标签,添加xx。
<a href="/xxx/xxx/xx/">添加</a>
<a href="{% url 'v1' %}">添加</a> <a href="{% url 'v2' %}">添加</a>
-
扩展
以后做权限管理,让name属性配合。
4. namespace
辅助name。
-
主路由 主路由是namespace
from django.urls import path, re_path, include # 很多功能,很多URL urlpatterns = [ path('api/', include("apps.api.urls",namespace='x1')), path('web/', include("apps.web.urls",namespace='x2')), ]
-
api/urls.py
from django.urls import path, re_path from . import views # 很多功能,很多URL urlpatterns = [ path('login/', views.login,name="login"), path('auth/', views.auth, name='auth'), ]
-
web/urls.py
from django.urls import path, re_path from . import views # 很多功能,很多URL urlpatterns = [ path('home/', views.home,name='home'), path('order/', views.order,name='order'), path('auth/', views.order, name='auth'), ]
以后再某个URL或者视图中反向生成:
from django.urls import reverse
url = reverse("x1:login") # /api/login/
url = reverse("x1:order") # /web/login/
url = reverse("x1:auth") # /api/login/
url = reverse("x2:auth") # /web/login/
两个扩展:
-
namespace需要设置app_name
urlpatterns = [ path('api/', include("apps.api.urls", namespace='x1')), ]
# 在指定APP的urls内定义appname from django.urls import path, re_path from apps.api import views # 很多功能,很多URL urlpatterns = [ path('login/', views.login, name="login"), path('auth/', views.auth, name='auth'), ] app_name = "api"
-
手动分发
手动分发 不会去 找namespace
赠送:
5. 最后的 / 如何解决?
在settings内设置
APPEND_SLASH = True
path('login/', views.login),
http://127.0.0.1:8000/login/ 成功
http://127.0.0.1:8000/login django,重定向301
http://127.0.0.1:8000/login/ 成功
path('login', views.login),
http://127.0.0.1:8000/login 成功
http://127.0.0.1:8000/login
http://127.0.0.1:8000/login/ 失败
APPEND_SLASH = False
path('login/', views.login),
http://127.0.0.1:8000/login/ 成功
http://127.0.0.1:8000/login 失败
path('login', views.login),
http://127.0.0.1:8000/login/ 失败
http://127.0.0.1:8000/login 成功
小结
-
常见 & 必须掌握
- 传统路由
- 路由分发
- name
-
差点意思
- 正则
- namapace
- 当前对象
-
补充小知识点(与django路由无关,看源码时有关)
-
关于 partial
def _xx(a1, a2): return a1 + a2 data = _xx(11, 22) print(data)
from functools import partial def _xx(a1, a2): return a1 + a2 yy = partial(_xx, a2=100) data = yy(2) print(data)
-