视图层

发布时间 2023-08-01 17:23:26作者: Py玩家

三板斧问题

在视图函数写函数跟普通函数不一样,它需要传一个request参数给形参,而这个参数只能在函数中局部使用

所有视图函数不能够没有返回值,并且返回值还必须是httpresponse对象

The view app01.views.index didn't return an HttpResponse object. It returned None instead.
翻译:视图app01.views。index没有返回HttpResponse对象它返回None。

三板斧返回的都是httpresponse对象

flask中request使用的就是全局变量

from ... import request
def index():
    pass

def func():
    pass

JSONResponse序列化

JSON格式的数据的作用

主要就是实现跨语言数据传输

现在实现跨语言数据的传输使用的都是json,在以前使用的是xml(微信支付朝微信的后端发送参数的时候,使用的就是xml)

JSON格式的数据特点:数据里面使用的是双引号

{"username":"kevin","age":18}

Python中的序列化

import json
json.dumps 序列化
json.loads    反序列化

JS中的序列化

JSON.stringify()序列化
JSON.parse() 反序列化

Django中的序列化

from django.shortcuts import render,HttpResponse
from django.http import JsonResponse


# Create your views here.
def index(request):
    import json
    d = {'username': 'kevin哈喽', 'age': 18}
    # d_json = json.dumps(d, ensure_ascii=False)
    # return HttpResponse(d_json)
    return JsonResponse(d,json_dumps_params={'ensure_ascii':False})

其他数据类型 需要把safe参数改为false

 l = [1, 2 , 3, 4]

return JsonResponse(l,safe=False)

from表单上传文件

前提

  1请求方式必须是post

  2.enctype必须是from-data

后端代码

def a_file(request):
    # post只能拿到文件数据之外的数据
    # print(request.POST)
    # 接搜文件数据
    print(request.FILES)
    if request.method=='POST':
        file_obj = request.FILES.get('myfile')
        print(file_obj)
        with open(file_obj.name,'wb') as f:
            for i in file_obj:
                f.write(i)
    return render(request, 'form_file.html')

前端页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <title>Title</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
    <input type="file" name="myfile">
    <input type="submit" value="提交">
</form>
</body>
</html>

request对象的其他方法

request.GET 
request.POST
request.FILES

request.path_info  #  /ab_request/ 获取路径
reqeust.path       #  /ab_request/  获取路径
request.get_full_path() # /ab_request/  /ab_request/? username=kevin&age=11获取路径以及详细信息
request.body # 现在先不学,它能够接收浏览器发过来的二进制数据,BBS项目中学

CBV的书写和FBV的写法

目前写的都是FBV:function based view 基于函数的视图
在视图文件中书写类 CBV:class based view 基于类的视图

postman的官网地址:https://www.postman.com/downloads/
apizza的挂网地址:http://www.apizza.net/

Django中所有类必须继承Django的View类

导入模块:from django.views import View

类里面的方法名字不能够随便写,目前只能写get post

URLs文件:

url(r'^a_file/', views.a_file.as_view()),

   # 访问这个地址必须是get请求方式
    def get(self, request):
        # get() takes 1 positional argument but 2 were given
        print("get")
        return HttpResponse("get")
# 访问这个方法必须是psot请求方式
    # 通过form表单发送post请求
    # 出了form表单,我们还可以使用工具来模拟
    def post(self,request):
        print("post")
        return HttpResponse("post")

cbv的源码分析

面试题:你都看过Django的哪些源码,简单说说

 CBV的源码、settings的源码、权限、频率、认证的、签发token的源码 

类名可以调用哪些方法:
1. 方法被@classmethod装饰器修饰的方法
类名来调用类方法有什么特殊之处:
会把类名自动当成第一个参数传递给方法的第一个形参cls
对象调用方法把对象自己当成第一个参数传给方法的第一个形参self

2. 被@staticmethod装饰器修饰的方法

 

看源码的步骤是先找到源码的入口
CBV的入口在哪里呢?

path('login/', views.MyLogin.as_view()),

views.MyLogin.as_view()

步骤

# 第一步
@classonlymethod
    def as_view(cls, **initkwargs):
        # cls:MyLogin
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            if hasattr(self, 'get') and not hasattr(self, 'head'):
                self.head = self.get
            self.setup(request, *args, **kwargs)
            if not hasattr(self, 'request'):
                raise AttributeError(
                    "%s instance has no 'request' attribute. Did you override "
                    "setup() and forget to call super()?" % cls.__name__
                )
            return self.dispatch(request, *args, **kwargs)
    
        return view
    
# 第二步:
path('login/', View.view),

# 第三步:
当请求来的时候,开始匹配路由login,就会调用View.view()

# 第四步
        def view(request, *args, **kwargs):
            # self = MyLogin(**initkwargs)
            self = cls(**initkwargs)
            """
                self: MyLogin()
            """
            return self.dispatch(request, *args, **kwargs) # 这句话是最重要的
 # 第五步:self.dispatch(request, *args, **kwargs) 
# 第六步:找到了View类里面的dispatch方法
第七步:
    def dispatch(self, request, *args, **kwargs):
            # getattr: 反射
            # 反射
            # getattr setattr delattr hasattr
            # handler = getattr(self, 'get', self.http_method_not_allowed)
            # handler = getattr(self, 'post', self.http_method_not_allowed)
            # handler就是方法名,对象
            # hander = get
            # hander = post
            # hander = self.http_method_not_allowed
        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)

 

问题:如何让我写的CBV类只支持get请求或者只支持post请求?

class MyLogin(View):
    http_method_names = ['get',] 让列表里面只有get请求即可
    # 类里面的方法名字不能够随便写,目前只能写get post等
    # 访问这个地址必须是get请求方式
    def get(self, request):
        # get() takes 1 positional argument but 2 were given
        print("get")
        return HttpResponse("get")

ps:源码是用来看的,不是用来改的,有时候也能够改,但是你不行,你这个阶段先不要想着改人家源码的

模版层

模板变量之分配

1.模板中取值一定使用的是句点符.
2.模板中的函数一定不能够加括号,他们会自动帮你加括号调用

后端代码

def func(request):
    d = {'kevin': 123}
    b = [1, 2, 3]

    def index():
        return HttpResponse('OK')

    return render(request, 'func.html', context=locals())

前端页面

def func(request):
    d = {'kevin': 123}
    b = [1, 2, 3]

    def index():
        return HttpResponse('OK')

    return render(request, 'func.html', context=locals())

 

模板之过滤器

Django自带的过滤器有好几十、但是我们没必要全部记住,只需要记住几个就行了
语法:
{{ obj|过滤器名称:参数 }} 变量名字|过滤器名称:变量

    default 默认值
    length    长度
        data 日期
    {#{{ res|default:'你很好啊' }}#}
    {#{{ res|length }}#}
    {#{{ res|filesizeformat }}#}
    {#{{ res|date:'Y-m-d' }}#}
    {#{{ res|truncatechars:9}}#}
    {#{{ res|safe }}#}