Django在启动时加载所有的路由
Django在项目启动时会遍历所有的urls.py文件加载所有的urlpatterns
例如myapp.urls中的urlpatterns会被进行加载:
urlpatterns = [
path('user/', handler),
]
加载过程中运行了列表中所有的path
函数,注意path
是个函数。在path
函数的源代码中可以看到传入了url字符串和handler视图函数,最终返回了一个URLPattern
,因此URLPattern
中封装了一个请求的请求路径、处理方法等等信息。
def _path(route, view, kwargs=None, name=None, Pattern=None):
...
if isinstance(view, (list, tuple)):
...
return URLResolver...
elif callable(view):
...
# 示例中我们的视图类调用as_view方法将自己封装成一个视图函数
# 因此会从这里最终返回一个URLPattern
return URLPattern...
elif isinstance(view, View):
...
raise TypeError...
else:
raise TypeError...
path = partial(_path, Pattern=RoutePattern)
Django在启动时就将所有路径的pattern收集起来,请求进来时就在其中进行初步匹配,根据请求找到对应的pattern就能获得对应的处理方法。
View视图的工作原理
对于Http请求来说,我们还要进一步根据不同的请求方法进行不同的处理,当然可以在视图函数中逐一判断:
def handler(request, *args, **kwargs):
if request.method == "GET":
return HttpResponse("GET")
if request.method == "POST":
return HttpResponse("POST")
但是使用一个视图类是一个更好的方法:
class MyView(View):
def get(self, request):
return HttpResponse("Get")
def post(self, request):
return HttpResponse("Post")
我们只需要定义方法,匹配的任务由View
类中定的dispatch
方法自动完成完成,源码摘要如下:
class View:
http_method_names = [
"get",
"post",
"put",
"patch",
"delete",
"head",
"options",
"trace",
]
...
def dispatch(self, request, *args, **kwargs):
# 根据传入的请求的请求方法,分配对应的处理方法
if request.method.lower() in self.http_method_names:
handler = getattr(
self, request.method.lower(), self.http_method_not_allowed
)
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs)
...
需要注意的是,path
要求我们传入一个函数作为处理方法,因此需要调用as_view()
方法把视图类包装成视图函数:
urlpatterns = [
path('user/', MyView.as_view()),
]