第四章:视图层

三板斧介绍

"""
HttpResponse
	返回字符类型
render
	返回HTML页面,并且可以在返回浏览器之前给HTML文件传值
redirect
	重定向
"""
# 视图函数必须要返回一个HttpResponse对象
HttpResponse是一个类
通过查看三板斧的源码可以看到返回的都是HttpResponse或者继承于它

JSONResponse对象

前后端数据交互需要使用json作为过渡,实现跨语言传输数据

def xx_json(request):
    # 创建一个字典
    user_dic = {'name': '刘苏成是dsb', 'age': '12', 'hobby': 'girl', 'gender': 'boy'}
    user_list = ['liu', 111, '刘']

    # 导入JSON模块
    import json
    # 序列化字典,ensure_ascii默认为True,自动把汉字编码成Unicode格式,把参数改为False就会写什么展示什么
    dic_json = json.dumps(user_dic, ensure_ascii=False)

    # 导入Django中的JsonResponse模块
    from django.http import JsonResponse
    # 想要写什么展示什么,通过查看JsonResponse的源码得知,添加json_dumps_params={'ensure_ascii': False}即可
    dic_json = JsonResponse(user_dic, json_dumps_params={'ensure_ascii': False})
    # JsonResponse模块默认不能序列化列表,添加safe=False就可以序列化列表了
    list_json = JsonResponse(user_list, safe=False, json_dumps_params={'ensure_ascii': False})

    return HttpResponse(list_json)


"""
	json_dumps_params={'ensure_ascii': False}:添加这个属性可以让JsonResponse模块写什么展示什么,不编码成unicode格式
	safe=False:添加这个属性可以让JsonResponse模块能序列化列表,默认是不能序列化列表的
"""

form表单上传文件后,后端获取文件

form表单上传文件记得改两个属性

# form表单要上传文件类型的数据,一定要记得改下面两个属性
1、method="post"
2、enctype="multipart/form-data"


<form action="" enctype="multipart/form-data" method="post"></form>

Django获取文件的方法

request.FILES  # 获取用户上传的文件数据
request.FILES.get('file')  # 获取一个文件对象
request.FILES.getlist('file')  # 获取所有文件对象
request.FILES.get('file').name  # 获取文件名
"""
request.POST不能获取到文件数据,需要使用request.FILES来获取文件
想要查看文件中的内容需要使用with文件操作
"""

使用实例

def files(request):
    if request.method == 'POST':
        # POST方法不能获取到文件对象
        quest = request.POST
        print(quest)

        # request对象方法:获取文件数据
        user_files = request.FILES
        # 获取文件对象
        files_obj = user_files.get('file')
        # 文件对象方法:获取文件名
        files_name = files_obj.name
        # 要查看获取的文件对象的内容,要使用with
        with open(files_obj.name, 'wb') as f:
            for info in files_obj.chunks():  # django推荐加上chunks方法,虽然加不加都是一样,都是一行行的读
                f.write(info)
                
        print(user_files)
        print(files_obj)
        print(files_name)
    return render(request, 'files.html')

request对象方法

request.method				# 返回大写的请求方法:POST/GET
request.POST				# 获取post请求
request.GET					# 获取get请求
request.FILES				# 获取文件
"""path与path_info是差不多的,记住一个就可以了"""
request.path				# 获取用户输入的路由:/app01/file/
request.path_info			# 获取用户输入的路由:/app01/file/
request.path_full_path()	# 获取用户输入的路由及问号后面的参数:/app01/file/?username=liu
request.body				# 原生的浏览器发过来的二进制数据,现在暂时了解,详细在后面

FBV与CBV简介

视图函数中可以是函数也可以是类

FBV就是函数

FBV使用

"""路由层"""
url(r'^login/', views.login)

"""视图层"""
def login(request):
    return render(request, 'login.html')

CBV就是类

CBV简单使用

"""路由层"""
url(r'^cbv/', views.MyCBV.as_view())

"""视图层"""
# 需要导入View模块
from django.views import View


# 特点:能够直接根据请求方式的不同直接匹配到对应的方法执行
# 需要继承View父类
class MyCBV(View):
    # 当请求为get请求时运行该函数
    def get(self, request):
        return render(request, 'files.html')

    # 当请求为post请求时运行该函数
    def post(self, request):
        return HttpResponse('这是post请求')

CBV源码剖析

1、解析路由层中的as_view是什么

1、解析路由层中的as_view是什么
"""
函数名/方法名 加括号执行优先级最高
猜测as_view()要么是被@staicmethod修饰的静态方法,
要么是被classmethod修饰的类方法
下面来查看源码
"""
# 通过查看as_view的源码得知,是被classmethod修饰的类方法(classmethod与classonlymethod差不多一个意思)
@classonlymethod
def as_view(cls, **initkwargs):
    pass

2、解析as_view返回了什么

2、解析as_view返回了什么
@classonlymethod
def as_view(cls, **initkwargs):
    def view(request, *args, **kwargs):
        pass
    return view
"""
查看as_view部分源码得知,这是一个闭包函数
最后的返回值是view
也就是当用户输入的地址匹配上的时候就会立刻执行as_view方法中的view方法
"""
# 所以路由层中的 url(r'^login/', views.MyCBV.as_view()), 可以变形为
url(r'^login/', views.view),  # 与FBV一模一样
"""所以CBV与FBV在路由匹配上本质是一样的,都是路由 对应 函数内存地址"""

3、查看view方法中写了什么

3、查看view方法中写了什么
# as_view方法中的view方法
def view(request, *args, **kwargs):
    
    self = cls(**initkwargs)  # cls是我自己写的类(视图函数中定义的类)
    # self = MyCBV(**initkwargs)  产生一个我们自己写的类的对象
    
    # 暂时不用看
    if hasattr(self, 'get') and not hasattr(self, 'head'):
        self.head = self.get
    
    # 给我们定义的类的对象赋值属性,也可以暂时不用管
    self.request = request
    self.args = args
    self.kwargs = kwargs
    
    """
    在看Python源码的时候一定要时刻提醒自己面向对象属性方法查找顺序
    	先从对象自己找
    	再从产生对象的类里面找
    	最后再去父类找
    	...
    总结:看源码只要看到了self点一个东西,一定要问自己当前这个self到底是谁
    """
    # 通过上述规律,dispatch方法在父类View中找到
    return self.dispatch(request, *args, **kwargs)

4、查看dispatch方法中写了什么

4、查看dispatch方法中写了什么
# dispatch是整个CBV的精髓所在
def dispatch(self, request, *args, **kwargs):
    # 以get请求为例
    # 获取当前请求的小写格式(lower方法转换大写为小写),然后判断当前请求是否合法
    if request.method.lower() in self.http_method_names:
        
        """
        getattr:反射
        通过字符串来操作对象的属性或者方法
        """
        handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        # handler = getattr(自己写的类的对象,'get', 当找不到get属性或者方法的时候就会用到第三个参数)
        # handler = 我们自己写的类里面的get方法
        
    else:
        # 请求不合法会报错
        handler = self.http_method_not_allowed
        
    # 最后自动调用我们类里面写的get方法
    return handler(request, *args, **kwargs)
"""
这就是为什么CBV可以根据不同的请求来做不同的操作的关键

getattr(self, request.method.lower(), self.http_method_not_allowed)
"""

5、总结:CBV内部执行流程

url(r'^login/', views.MyCBV.as_view())

"""
MyCBV是我们自己写的类,里面有get和post两个方法,分别对应get和post请求
用户输入loign,调用as_view方法,把MyCBV类传进去
as_view是一个闭包函数,返回view方法,就相当于 url(r'^login/', views.view)
view方法把我们写的类产生一个对象,然后点dispatch方法,进入CBV的精髓所在
dispatch先判断请求是否合法,合法后通过反射:getattr方法,看我们写的类中是否有get或者其他合法请求的方法
我们的类中有get或者其他合法请求的方法,dispatch自动帮我们调用该方法,所以CBV才能根据不同的请求来做相应的操作
"""
posted @   7七柒  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示