• Django(五、视图层)


    一、视图层

    1.视图函数返回值的问题

    当视图函数返回为一个空的时候会报错

    def index(request):
        # return HttpResponse('is index!')
        return None
    
    • 1
    • 2
    • 3

    在这里插入图片描述
    把上面一句话翻译过来就是视图函数必须返回一个HttpResponse对象

    2.三板斧的使用

    HttpResponse: 字符串
    render:渲染html页面
    redirect:重定向的

    1.HttpResponse
        class HttpResponse(HttpResponseBase)pass
         # 括号内直接跟一个具体的字符串作为响应体
    
    2.render
    def render(request, template_name, context=None, content_type=None, status=None, using=None):
    
        request: 用于生成响应的请求对象。
    	template_name:要使用的模板的完整名称,可选的参数
    	context:添加到模板上下文的一个字典。默认是一个空字典。如果字典中的某个值是可调用的,视图将在渲染模板之前调用它。
    	render方法就是将一个模板页面中的模板语法进行渲染,最终渲染成一个html页面作为响应体。
    	
        content = loader.render_to_string(template_name, context, request, using=using)
        return HttpResponse(content, content_type, status)
    
    3.redirect
    def redirect(to, *args, permanent=False, **kwargs):
      	传递要重定向的一个硬编码的URL或者路由
        redirect_class = HttpResponsePermanentRedirect if permanent else HttpResponseRedirect
        return redirect_class(resolve_url(to, *args, **kwargs))
        eg: redirect内部是继承了HttpRespone类
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    结论:在视图文件中写视图函数的时候不能没有返回值,默认返回的是None,但是页面上会报错,用来处理请求的视图函数都必须返回httpResponse对象。

    二、JsonReponse序列化类的使用

    前后端数据交互需要使用json作为序列化,实现跨语言数据传输。

    1. 混合开发项目:前端页面和后端代码写到一块
    2. 前后端分离项目:前端是一个项目,后端是一个项目,后端只需要写接口

    前端序列化:JSON.stringify(),JSON.parse()
    后端序列化:json.dumps(), json.loads()

    1.json序列化

    # 导入模块
    import json
    
    def index(request):
        # 将后端字典序列化发送到前端
        user_dict = {'name':'jack','age':18}
       # 先转成json格式字符串
        json_str = json.dumps(user_dict)
        # 将该字段返回
        return HttpResponse(json_str)
    
     # ensure_ascii 内部默认True自动转码,改为False不转码,只生成json格式,双引号
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2.JsonResponse序列化

    # 导入JsonResponse模块
    from django.http import JsonResponse
    def index(request):
        # 将后端字典序列化发送到前端
        user_dict = {'name': 'jack你好', 'age': 18}
    # JsonResponse自动编码并返回给前端页面
    return JsonResponse(user_dict,json_dumps_params={'ensure_ascii':False})
    
    本质看源码:
    user_dict,json_dumps_params={'ensure_ascii':False} :解决前端汉字转码问题
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述JsonResponse主要序列化字典 针对非字典的其他可以被序列化的数据需要修改safe参数为False(是在前端页面更改的)

    列表序列化

    def index(request):
        user_dice = [1, 2, 3, 4, 5, 6, 7, 8, 9]
        return JsonResponse(user_dice, safe=False)
        是否可以被序列化看通过json.JSONEncoder 查看源码
    
    • 1
    • 2
    • 3
    • 4

    form表单上传文件

    1.图片文件上传

    views.py

    def form_file(request):
        if request.method == 'POST':  # 当点击提交按钮才会走这一步
            form_obj = request.FILES.get('myfile')  # 获取上传的文件
            form_name1 = form_obj.name  # 获取上传文件的文件名
            import uuid
            random_str = str(uuid.uuid4())  # 随机字符串
            form_name = random_str + '.' + form_name1.split('.')[-1]  # 按点切分取最后一个数据
            with open(form_name, 'wb') as f:  
                for line in form_obj:  # 写入文件
                    f.write(line)  
        return render(request, 'form_file.html')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    form_file.html

    数据要携带数据,下述两个参数写成下述的参数
    {# 1.method指定成post  2.enctype换成form-date #}
    <form action="" method="post" enctype="multipart/form-data">
        <input type="file" name="myfile">
        <input type="submit">
    </form>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    request对象方法

    1.获取请求方式POST/GET
    request.method
    一个字符串,表示请求使用的HTTP 方法。必须使用大写。
    
    2.request.POST
    获取POST请求提交普通的键值对数据 一个类似于字典的对象,如果请求中包含表单数据,则将这些数据封装成
    
    3.获取GET请求
    request.GET
    获取GET请求	一个类似于字典的对象,包含 HTTP GET 的所有参数
    
    4.获取文件
    request.FILES
    一个类似于字典的对象,包含所有的上传文件信息。
    FILES 中的每个键为<input type="file" name="" /> 中的name,值则为对应的数据。
    注意,FILES 只有在请求的方法为POST 且提交的<form> 带有enctype="multipart/form-data" 的情况下才会包含数据。否则,FILES 将为一个空的类似于字典的对象。
    
    5.原生的浏览器发过来的二进制数据
    request.body  
    一个字符串,代表请求报文的主体。在处理非 HTTP 形式的报文时非常有用,
      例如:二进制图片、XML,Json等。
    
    6.拿到路由
    request.path 
    个字符串,表示请求的路径组件(不含域名)
    
    7.拿到路由
    request.path_info
    
    8.能过获取完整的url及问号后面的参数 
    request.get_full_path() 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    三、FBV与CBV

    FBV
    	基于函数的视图
    	def index(request):return HttpResponse对象
    
    CBV
    	基于类的视图
    	from django import views
      	 class MyLoginView(views.View):
            def get(self, request):
                return HttpResponse('from CBV get function')
    
            def post(self, request):
                return HttpResponse('from CBV post function')
    	path('login/', views.MyLoginView.as_view())
    	会自动根据请求方法的不同自动匹配对应的方法并执行
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    CBV源码解析

    1.从CBV的路由匹配切入
    	path('login/', views.MyLoginView.as_view())
            1.类名点名字(名字的查找问题)
            2.类名点名字并加括号调用(静态方法、绑定给类的方法)
    2.函数名加括号执行优先级最高 项目一启动就会自动执行as_view方法
    	path('login/', views.view)  # CBV路由本质还是FBV
    3.浏览器地址栏访问login路由需要执行view函数
    	1.产生我们自己编写类的对象
     	2.对象调用dispatch方法(注意查找顺序)
    4.研究父类中的dispatch方法
    	获取当前请求方法并转小写 之后利用反射获取类中对应的方法并执行
      
    
    class View:
         @classmethod
         def as_view(cls, **initkwargs):
            def view(request, *args, **kwargs):
                self = cls(**initkwargs)
                return self.dispatch(request, *args, **kwargs)
         def dispatch(self, request, *args, **kwargs):
             handler = getattr(self, request.method.lower())
             return handler(request, *args, **kwargs)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    分步解析
    1.从CBV的路由匹配切入,path(‘login/’, views.MyLoginView.as_view()),根据观察路由后面的函数可知,MyLoginView是我们自己定义的类,但类点一个(as_view())证明as_view()是一个方法,但是as_view既不是自定义类中的属性也不是自定义类的方法,由此可得,只要往类的父类里面去寻找。

    2.MyLoginView.as_view(),类名点一个属性加括号,有两种情况

       1.as_view是一个普通函数,是通过staticmethod绑定给类的方法
       2.绑定给类的方法,@classmethod修饰的函数  类调用第一个参数就是类自身 对象也可以调用并且会自动将产生该对象的类当做第一个参数传入
    
    • 1
    • 2

    3.通过ctrl点View查看源码可知
    在这里插入图片描述
    发现这个返回值仍然不是一个明确的函数,我们还需要查看dispatch方法的返回值,在此之前,我们需要分析出,dispatch是绑定对象的动态方法,这个self是由我们自己定义的类所产生的对象
    4.查看dispatch函数,由于我们对象及其类的属性中都没有dispatch,所以这个函数还是我们父类View的类体函数

    在这里插入图片描述
    至此,我们就剖析出,我们的as_view()函数做了这么几件事:

    封装了一个函数,作为对应路由的函数
    封装的函数中,让我们的自定义类产生了一个对象,并让对象执行方法dispatch返回结果
    dispatch辨认了请求方式,根据请求方式返回了某个类体函数的结果(HttpResponse对象)
    所以视图类,就是将一个路由根据请求方式又重新划分了不同的视图函数,不必再在视图函数中对请求方式进行判断了。

  • 相关阅读:
    OpenAI“杀疯了”,GPT–4o模型保姆级使用教程!一遍就会!
    IEnumerable与IQueryable延迟加载
    ElasticSearch学习(一)
    微信小程序开发的OA会议之会议个人中心的页面搭建及模板,自定义组件的学习
    故障排查:k8s节点不可用(rancher/hyperkube:v1.21.14-rancher1 Restarting)
    OpenCV C++ 图像处理实战 ——《多二维码识别》
    六级阅读3大核心技巧-因果关系题:如何识别因果
    windows 电脑改成安卓桌面
    spring实现AOP
    搜索+剪枝,LeetCode 216. 组合总和 III
  • 原文地址:https://blog.csdn.net/shiyaopeng11/article/details/134405409