您的当前位置:首页正文

Django 视图层 —— 基础用法,以及 CBV 是如何匹配的

2024-11-23 来源:个人技术集锦

视图层

  • Django 接收到浏览器的发送的请求之后, 进行 URL 匹配,找到对应的视图进行响应。

用法

FBVCBV

  • FBV(function base views)使用视图函数处理请求

  • CBV(class base views) 使用视图类处理请求

views.py:

from django.http import HttpResponse
from django.views import View


# path('login/', views.login),
def login(request):
    return HttpResponse("login")


# path('user/', views.UserView.as_view()),
class UserView(View):
    def get(self, request):
        return HttpResponse("GET")

    def post(self, request):
        return HttpResponse("POST")

请求的参数

request:

print(type(request))  # <class 'django.core.handlers.wsgi.WSGIRequest'>

from django.core.handlers.wsgi import WSGIRequest
# 点击 WSGIRequest 即可查看参数
# 补充:
	# WSGIRequest 中装饰器 @property 的作用:可以不用加括号
    	# 如:request.GET()  ->  request.GET
        # @cached_property 会添加一个缓存,访问同一个参数时减少解析次数
	# QueryDict: 特殊的字典,key 可以重复
    # POST = property(_get_post, _set_post) 中 property 的作用:
    	# p = obj.POST 就执行 _get_post,obj.POST = 123 就执行 _set_post

# 常用的参数有:
request.method
request.GET
request.POST
request.FILES
request.path_info
request.body
request.resolver_match
request.session

响应的数据

# HttpResponse  ->  构建响应体和响应头
HttpResponse("login")

# class JsonResponse(HttpResponse):  # ...
JsonResponse({"status": True, "return": "login"})

# xxx.txt: "login"
render(request, "xxx.txt")
render(request, "xxx.html")

# 重定向
    # 永久重定向:permanent=True,状态码:301,多用于旧网址被废弃了要转到一个新的网址
    # 临时重定向(默认):permanent=False,状态码:302,比如用户没有登陆要跳转到登录页面

# 响应头里面放一个 Location ,浏览器读取到之后会像 Location 指向的网址再次发送请求
redirect("http://xx.com")

源码

CBV 的匹配

# login/  -->  views.login
path('login/', views.login),

# user/  -->  as_view()方法的返回值
path('user/', views.UserView.as_view()),

UserView.as_view() -> View.as_view(): 返回 view 函数,如果是 GET 请求,则返回的就是 UserView.get()

# path('user/', views.UserView.as_view()), GET 请求

def dispatch(self, request, *args, **kwargs):
    # 尝试分派到正确的请求方法
    if request.method.lower() in self.http_method_names:
        # handler = self.request.method.lower()  =>  UserView.get()
        handler = getattr(
            self, request.method.lower(), self.http_method_not_allowed
        )
    else:
        # 请求不存在或者请求不在批准的列表里面
        handler = self.http_method_not_allowed
    return handler(request, *args, **kwargs)  # UserView.get()

    
def as_view(cls, **initkwargs):
    """Django 处理 HTTP 请求的入口"""
    # cls: <class 'app.views.UserView'>
        # cls.http_method_names = ["get","post","put","patch","delete","head","options","trace",]
        # cls.view_is_async = False

    # initkwargs: {}
    
    for key in initkwargs:
        # 用户传入 HTTP 方法名相同的参数时,会报错。目的是避免意外覆盖类视图的 HTTP 请求处理方法
        # 如:as_view(get='some_value') 会发生报错
        if key in cls.http_method_names:
            raise # ......
        if not hasattr(cls, key):
            raise # ......
	
    # 闭包
    def view(request, *args, **kwargs):
        # 实例化 UserView 对象
        # self = UserView()
        self = cls(**initkwargs)
        
        # 初始化各个参数
        # self.request = request ...
        self.setup(request, *args, **kwargs)
        
        if not hasattr(self, "request"):
            raise # ......
            
        # 返回 self.dispatch  ->  UserView.get()
        return self.dispatch(request, *args, **kwargs)

    
    view.view_class = cls  # <class 'app.views.UserView'>
    view.view_initkwargs = initkwargs  # {}

    # ......

    return view

显示全文