首页 > 其他分享 >视图层

视图层

时间:2023-04-27 20:45:07浏览次数:30  
标签:get self request 视图 json HttpResponse view

目录

三板斧

本质

用来处理请求的视图函数都必须返回HttpResponse对象

# 可以查看源码

1.HttpResponse():肯定是返回HttpResponse对象
	
2.render():是一个函数,它的源码中返回值也是一个HttpResponse对象
return HttpResponse(content, content_type, status)

3.redirect():它的返回值redirect_class继承的类中往上一直寻找,祖先有个类是HttpResponse

思考
为什么删除数据之后要直接重定向,而不可以到展示数据的页面?

redirect('/index/')  # index函数的功能是展示展示一个userlist页面

render(request, 'userlist.html'),

解析:

  1. 使用render这种方式,网址不会变化,还是原来的,这样修改过后就只能展示一次列表,没有了能够在列表上编辑和修改的功能了。
  2. 想要网址也变化,就需要在前端form的actioan参数中添加'userlist.html'网址,但是这个网址是POST提交数据的网址,就与修改数据的网址产生了冲突。

综上,所以还是直接写重定向好。

HttpResponse和redirect的区别

HttpResponse和redirect都是Django中常用的返回响应给客户端的方法,但是它们的作用不同,具体区别如下:

  1. HttpResponse:HttpResponse是返回包含内容的响应,通常用于返回HTML页面或者某些文本信息。通过HttpResponse可以返回一个包含字符串、字节流或者文件的响应。需要注意的是,HttpResponse只是将请求处理后的响应给了浏览器,但是并没有改变浏览器的地址栏。

  2. redirect:redirect是重定向到指定URL的方法,通常用于在处理请求后将用户跳转到新的页面,比如登录成功后跳转到主页。通过redirect可以返回一个HTTP响应对象,告诉浏览器要跳转到哪一个URL。需要注意的是,在使用redirect时,浏览器会向新的URL再次发送请求,这就意味着在处理跳转后的请求时,与之前的请求进行的操作是不同的。

总的来说,HttpResponse和redirect的作用不同,使用场景也不同。如果需要返回某个内容(比如HTML页面),可以使用HttpResponse;如果需要跳转到某个URL,可以使用redirect。

JsonResponse

json格式的数据的作用:可以进行跨语言传输

json格式数据举例:

{"username":"kevin"}
# 用双引号

复习之前学习python中和js中序列化

1.python中:
    序列化:   json.dumps()
    反序列化:  json.loads()

2.js中:
    序列化:   JSON.stringify()
    反序列化:   JSON.parse()

在django中的序列化:

1.正常使用

def ab_json(request):
    user_dict = {'username': 'tank', 'age': 20}
    # 方式一:使用python序列化
    # import json
    # json_str = json.dumps(user_dict)

    # Django中序列化
    json_str = JsonResponse(user_dict)
    return HttpResponse(json_str)

2.修改字符编码

def ab_json(request):
    user_dict = {'username': 'tank哈哈哈', 'age': 20}
	# python中序列化修改字符编码
    # import json
    # json_str = json.dumps(user_dict,ensure_ascii=False)
    # Django中序列化修改字符编码
    json_str = JsonResponse(user_dict, json_dumps_params={'ensure_ascii': False})
    '''就可以显示中文了'''
    # 当你遇到一些新的方法的时候,点进去看一看,追一追代码,大概应该能看懂
    return HttpResponse(json_str)

可以查看源码,查看底层的逻辑。JsonResponse的底层还是dumps,只是在dumps函数基础之上做了封装。

源码分析:

data = json.dumps(data, cls=encoder, **json_dumps_params)
**json_dumps_params有为空的判断
# 添加参数:json_dumps_params={'ensure_ascii': False}之后的变化
====>
data = json.dumps(data, cls=encoder, **{'ensure_ascii': False})
====>
data = json.dumps(data, cls=encoder, ensure_ascii=False)

3.序列化列表

def ab_json(request):
    l = [1, 2, 3, 4] 
    # python中序列化列表,变成数组形式
    
    # Django中序列化列表
    # 为了允许序列化非字典对象,要将安全参数设置为False。
    json_str = JsonResponse(l,safe=False)
    return HttpResponse(json_str)

源码:

JsonResponse是个类
里面__init__方法,中设置参数safe=True
存在一个判断条件:
# 如果safe是真并且data不是字典类型,就会主动抛出异常。
if safe and not isinstance(data, dict):
    raise TypeError(
        'In order to allow non-dict objects to be serialized set the '
        'safe parameter to False.'
    )

上传文件

表单上传文件需要满足的条件是:

  1. 请求方式需要是:post
  2. enctype---->form-data

django后端获取文件类型的数据:request.FILES

具体使用:

前端html:

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

views.py

def ab_file(request):
    # 接收用户提交过来的数据
    # request.POST获取普通数据(输入、选择)
    print(request.POST) # <QueryDict: {'username': ['SDASD']}>
    
    # request.FILES,获取文件数据(上传)
    print(request.FILES) # <MultiValueDict: {'myfile': [<InMemoryUploadedFile: 123.png (image/png)>]}>
    # 'myfile':文件对象
    
    # 先得到文件对象
    file_obj = request.FILES.get('myfile')
    # 读取图片文件
    with open(file_obj.name, 'wb') as f:
        # 可以一次性读取
        # f.write(file_obj) 
        # 文件比较多的时候,建议这种方式
        for line in file_obj:  # 文件对象支持循环,就可以一行一行读取
            f.write(line)
    return render(request, 'ab_file.html')

Django视图层-FBV与CBV

  • FBV:基于函数的视图
# function based view

def index(request):return HttpResponse对象
  • CBV:基于类的视图
# class based view

class Mylogin(View): def get(reguest): pass

FBV中request对象的几个方法

# GET POST FILES method
# path path_info get_full_path() body

def index(request):
    print(request.path)  # /index/
    print(request.path_info)  # /index/
    print(request.get_full_path()) # 接收路径的全部内容,连参数也能拿到 /index/?username=kevin
    print(request.body)  # 浏览器发过的二进制数据
    return HttpResponse('ok')

CBV

路由:

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

views.py:

# 新建类
from django.http import HttpResponse
from django.views import View

class Mylogin(View):  # CBV必须继承View类
    # 通过get请求方式会访问到这个方法
    def get(self, request):
        return HttpResponse('get')

    # 通过post请求方式会访问到这个方法
    def post(self, request):
        return HttpResponse('post')

'''CBV会自动根据请求方法的不同自动匹配对应的方法并执行'''

CBV的源码剖析

看源码首先先找入口,CBV的入口就在路由:

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

分析步骤:

  1. as_view()是类View里面的as_view方法
    第二个参数是as_view方法里面的view的函数内存地址
  2. 当http请求过来的时候,会自定触发view的执行
  3. view()中的返回值self.dispatch()
  4. View类里面的dispatch方法

详细分析:

1.从路由入口

url(r'^login/', views.Mylogin.as_view()),  # 类名调用方法(1.可能是绑定给类的方法,2.可能是静态方法)

我们在MyLogin类中并没有写as_view()方法, 可能会在父类中。 ---> 看父类View()

2.父类View(),内部有as_view()方法

# class classonlymethod(classmethod)
# 这个装饰器继承了classmethod类,可以把它当成classmethod,但功能更加强大

@classonlymethod  
def as_view(cls, **initkwargs):

'''结果as_view()是绑定给类的方法'''

3.as_view()方法详细

'''使用是,as_view()加括号是调用了这个方法'''

@classonlymethod
def as_view(cls, **initkwargs):  
    # 类来调用方法,会把类名当成第一个参数传给方法的第一个形参
    # cls:Mylogin
    for循环...,参数验证
    # 闭包,定义在函数内部的函数
    def view(request, *args, **kwargs):pass
    return view  # 返回值是函数名

######
views.MyLogin.as_view()-------->View类里面的as_view方法中的view方法的内存地址

url(r'^login/', views.Mylogin.as_view()), 
# 类似于url(r'^login/',views.view),本质上是放的还是函数的内存地址

当访问这个地址时,是向服务端发送了个请求,请求来了,会自动触发对应视图函数的执行,即view函数的执行。

4.view()函数详细

def view(request, *args, **kwargs):
    self = cls(**initkwargs)
    # cls是使用了外部函数中的值,cls:Mylogin
    # self = Mylogin(**initkwargs),类名加括号是实例化一个对象
    # self:是我们写的类产生的对象
    if hasattr(self, 'get') and not hasattr(self, 'head'):
        self.head = self.get
	self.request = request
	self.args = args
	self.kwargs = kwargs
    # 以上就是传参数
    
    '''在看跟面向对象相关的源码的时候,一定要区分开self是谁'''
    # self是我们自己写的类产生的对象
    # 对象点方法的查找顺序:先从自己的类中查找,没有去父类中查找
	return self.dispatch(request, *args, **kwargs)
'''

view函数执行完毕之后,来到了return self.dispatch(request, *args, **kwargs)

对象调方法,是把对象自己当成第一个参数传入
'''	

5.View类中的dispath()方法

def dispatch(self, request, *args, **kwargs):
    # 请求方式转成小写
    # self:我们自己写的类产生的对象
    # self.http_method_names,是对象点属性,对象名称空间中没有,Mylogin类中也没有,去父类View中找。
    # View类中有:http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'],View类定义的8中请求方式
    if request.method.lower() in self.http_method_names:
        # 反射,getattr(self, 'get', 默认值)
        # 从对象中找get方法,没有执行第三个参数
        # 找到,handler是get函数的内存地址
        handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
	else:  # 如果不是上面8中请求,方法不允许 
		handler = self.http_method_not_allowed
    '''所以我们定义的类中的方法名不可以随意写,写的方法必须是8中请求方式中的一种'''
	return handler(request, *args, **kwargs)  # get(request, *args, **kwargs),get加括号调用,把参数传给get函数
'''所以我们定义类,写方法时,需要写request参数'''

我们要熟练口头表述出步骤逻辑。
这是最简单的源码,后面还会学习权限、频率等的源码。这些源码更加复杂。

使用操作

我们写的类中的使用源码的两个简单操作:

1.我写的这个类只允许get和poat请求,怎么做?
类的内部定义一个类属性http_method_names,名字不要写错!!!

rom django.views import View
class MyLogin(View):
    # 我写的这个类只允许get和poat请求
    http_method_names = ['get', 'post']
    
    def get(self, request):  # 通过get请求方式会访问到这个方法
        return HttpResponse('get')
    
    def post(self, request):  # 通过post请求方式会访问到这个方法
        return HttpResponse('post')

解析:
对象点属性时,是先从产生对象的这个类中查找,找到就直接返回,我们定义了一个属性,就不会再使用源码中定义的属性了。并且只会影响这一个类,对其他的类不会产生影响。

2.View类定义一个dispath()

如果我们自己写的类中也定义了一个dispath()方法,就会先查找到我们自己的dispath()方法,不会去父类中查找dispath了。

from django.views import View
class AddPublish(View):
    def dispatch(self, request, *args, **kwargs):
        print(request)
        print(args)
        print(kwargs)
        # 可以写类似装饰器的东西,在前后加代码
        obj=super().dispatch(request, *args, **kwargs)
        return obj

    def get(self,request):
        return HttpResponse('get')
    def post(self,request):
		print(request.POST)
        return HttpResponse('post')

对应知识点:

  1. 类来调用方法:

    • 被@classmethod装饰器修饰的方法
    • 被@staticmethod装饰器修饰的方法
  2. 函数名加括号执行优先级最高 项目一启动就会自动执行as_view方法

  3. 对象点方法:
    先从自己类中查找,没有去继承的父类中查找

  4. 对象点属性的查找顺序:
    先从自己对象属性里面去找,如果找到了,直接返回,如果找不到,在去产生这个对象的类中取查找,如果也没有,去继承的父类中查找,还没有,则报错。

  5. getattr():

    反射指的是'通过字符串来操作对象的属性'

    getattr(对象,'对象属性的字符串',默认值)
    

    给了第三个参数,如果属性存在,就输出属性值,属性不存在,输出默认值,不会改变对象字典

标签:get,self,request,视图,json,HttpResponse,view
From: https://www.cnblogs.com/zjyao/p/17360095.html

相关文章

  • 高性能、快响应!火山引擎 ByteHouse 物化视图功能及入门介绍
    更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群物化视图是指将视图的计算结果存储在数据库中的一种技术。当用户执行查询时,数据库会直接从已经预计算好的结果中获取数据,而不需要重新计算视图。具体来说,物化视图是一种以表格形式存储的结果......
  • 表和视图的区别
    表和视图的区别区别:1、视图是已经编译好的sql语句。而表不是2、视图没有实际的物理记录。而表有。3、表是内容,视图是窗口4、表只用物理空间而视图不占用物理空间,视图只是逻辑概念的存在,表可以及时对它进行修改,但视图只能由创建的语句来修改5、表是内模式,试图是......
  • MFC-Create动态创建列表视图控件
     BOOLbb=mylist.Create(LVS_SMALLICON|WS_DLGFRAME,rect,this,10001);//动态创建列表视图控件/*参数1:DWORDdwStyle列表视图控件的风格标准样式:LVS_ALIGNLEFT显示格式是大图标或小图标时,标签......
  • Django之视图函数层 (必会三板斧 JsonResponse对象 request对象获取文件 FBV与CBV
    目录视图层之必会三板斧用来处理请求的视图函数都必须返回HttpResponse对象情况一:啥也不返回这里会报一个没有返回HttpResponse对象的错误,由此可见必须要返回一个HttpResponse对象情况二:返回HttpResponse对象点击Ctrl键查看源码可见是HttpResponse类,所以会返回一个值情......
  • Django框架——路由分发、名称空间、虚拟环境、视图层三板斧、JsonResponse对象、requ
    路由分发#Django支持每个应用都可以有自己独立的路由层、静态文件、模版层。基于该特性多人开发项目就可以完全解耦合,之后利用路由分发还可以整合到一起多个应用都有很多路由与视图函数的对应关系这个时候可以拆分到各自的路由层中使用路由分发之前总路由直接是路由与视图......
  • drf-视图集、路由系统、action装饰器
    1.9个视图扩展类1.两个视图基类:APIView、GenricAPIView2.5个视图扩展类:CreateModelMixin,UpdateModelMixin,RetrieveModelMixin,ListModelMixin,DestroyModelMixin3.9个视图子类:CreateAPIView,DestroyAPIView,ListAPIView,RetrieveAPIView,UpdateAPIView,ListCreateAPIView,......
  • Django4全栈进阶之路11 view视图
    在Django4中,视图(View)是一个处理请求并返回响应的Python函数或类的组合。视图函数通常是处理请求的主要逻辑,因此它是DjangoWeb应用程序的重要组成部分。视图函数的基本结构如下:fromdjango.httpimportHttpResponsedefmy_view(request):#处理请求的代码r......
  • sqlserver视图 to mysql表
    sqlserver视图tomysql表有两台服务器,是同一个内网。sqlserver这台只能内网访问mysql这台可内可外现在需要将sqlserver的一个视图数据,每天凌晨同步到另外一台服务器的mysql数据库里共参考:安装sqlserverhttps://www.linuxprobe.com/centos7-instal-mssql-2019.html创......
  • SpringMVC-响应数据和结果视图
    一、返回值分类1、字符串@Controller@RequestMapping("test")publicclasstest{@RequestMapping("testString")publicStringtestString(Modelmodel){Useruser=newUser();user.setUserName("李四");......
  • SpringMvc 视图解析
    重定向forward前缀若要返回/WEB-INF/pages/success.jsp,则直接return"success";即可。若要返回webapp下的helloworld.jsp页面:相对路径../../hello,需return"../../helloworld";forward前缀,转发一个页面,不会进行拼串。需return"forward:/helloworld.jsp";格式:forward:转......