DRF视图基类使用方法

【 一 】drf之请求

请求对象Request

【 0 】前言

​ 在 Python 中,通常通过 request 对象来处理 HTTP 请求,尤其是在 web 开发中,比如使用 Django、Flask 等框架时会经常接触到这个对象。request 对象是框架提供的,用于封装客户端发送的 HTTP 请求,并提供了访问请求头、请求体、请求参数等信息的方法和属性。

对于 Django 框架而言,request 对象是 Django 中视图函数的一个参数,表示客户端发送的 HTTP 请求。下面是一些常用的 request 对象的属性和方法:

  1. 属性
    • request.method:HTTP 请求方法,如 GET、POST、PUT、DELETE 等。
    • request.GET:包含 GET 请求参数的 QueryDict 对象。
    • request.POST:包含 POST 请求参数的 QueryDict 对象。
    • request.FILES:包含文件上传的文件对象的字典。
    • request.path:请求的路径部分,不包括域名和查询参数。
    • request.headers:请求头部信息,以字典形式保存。
  2. 方法
    • request.get():获取指定 key 的 GET 请求参数值。
    • request.post():获取指定 key 的 POST 请求参数值。
    • request.getlist():获取指定 key 的参数值列表,适用于多个相同 key 的参数情况。
    • request.is_ajax():判断请求是否为 AJAX 请求。
    • request.user:当前登录用户的信息(需要身份验证的情况下)。
from rest_framework.request import Request
# 该Request没有继承django原生的HttpRequest

REST framework 传入视图的request对象不再是Django默认的HttpRequest对象,而是REST framework提供的扩展了HttpRequest类的Request类的对象。

REST framework 提供了Parser解析器,在接收到请求后会自动根据Content-Type指明的请求数据类型(如JSON、表单等)将请求数据进行parse解析,解析为类字典[QueryDict]对象保存到Request对象中。

Request对象的数据是自动根据前端发送数据的格式进行解析之后的结果。

无论前端发送的哪种格式的数据,我们都可以以统一的方式读取数据。

【 1 】常用属性

'''
request.data 字典
返回解析之后的请求体数据。类似于Django中标准的request.POST和request.FILES属性,但提供如下特性:


包含了解析之后的文件和非文件数据


包含了对POST、PUT、PATCH请求方式解析后的数据


利用了REST framework的parsers解析器,不仅支持表单类型数据,也支持JSON数据


request.query_params
request.query_params与Django标准的request.GET相同,只是更换了更正确的名称而已。
@property
def query_params(self):
return self._request.GET
'''

【 2 】补充:

查找顺序:

  • 先从视图类中找
  • 项目的配置文件中找settings.py
  • 最后再到DRF的默认配置去找drf–>settings.py文件

drf的Request对象可以调用django原生的request对象的属性和方法 这是因为drf的Request类用_request属性封装了原生django的request

  	# 这是因为drf的Request类重写了__getattr__方法,代理了原生了request        
self._request = request	# request是django原生的request
def __getattr__(self, attr): # 当调用的属性不存在时触发__getattr__()
            return getattr(self._request, attr) 

【 1 】控制解析格式使用

# 3 控制解析格式使用
	-1 视图类中局部使用
    class RequestView(APIView):
    	parser_classes = [JSONParser, FormParser]
    -2 全局配置文件使用
        REST_FRAMEWORK = {
        'DEFAULT_PARSER_CLASSES': [
            # 'rest_framework.parsers.JSONParser',
            # 'rest_framework.parsers.FormParser',
            'rest_framework.parsers.MultiPartParser',
        ],
    }
    -3 全局配了,局部重新配置
        class RequestView(APIView):
    	parser_classes = [ FormParser]
  • views.py

  • JSONParser == raw

  • FormParser == form-data

  • x-www-form-urlencoded == FormParser

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.parsers import JSONParser,FormParser,MultiPartParser
class ReqsuetView(APIView):
    # 第一种方法
    # 设置解析器类列表,包括 JSONParser 和 FormParser、MultiPartParser

    parser_classes = [JSONParser, FormParser,MultiPartParser]

    def post(self,request):
        # form-data格式携带文件和数据---> 数据在request.data 中 ---> 文件request.data,也在request.FILES中
        # 但是request.data 这种方法不推荐
        print(request.data)
        #< QueryDict: {'myssda': [ < TemporaryUploadedFile: ffmpeg.dll(application / x - msdownload) >]} >
        FILES = request.FILES
        print(FILES)
        # < MultiValueDict: {'myssda': [ < TemporaryUploadedFile: ffmpeg.dll(application / x - msdownload) >]} >
        return Response({"code":'200',"msg":request.data})
  • settings.py配置文件

DEFAULTS = {
    # 去rest_framework源码中去找settings.py文件
    # 可以使用三种方法
    'DEFAULT_PARSER_CLASSES': [
        'rest_framework.parsers.JSONParser',
        # 'rest_framework.parsers.FormParser',
        # 'rest_framework.parsers.MultiPartParser',
    ],

}
# 第三种
全局配了,局部重新配置(不推荐使用)
class RequestView(APIView):
parser_classes = [ FormParser]

【 二 】drf之响应

响应对象Response

from rest_framework.response import Response
# 该Response继承了django原生的HttpResponse

【 0 】前言

REST framework提供了一个响应类Response,使用该类构造响应对象时,响应的具体数据内容会被转换(render渲染)成符合前端需求的类型。

REST framework提供了Renderer 渲染器,用来根据请求头中的Accept(接收数据类型声明)来自动转换响应数据到对应格式。如果前端请求中未进行Accept声明,则会采用默认方式处理响应数据,我们可以通过配置来修改默认响应格式。

可以在rest_framework.settings查找所有的drf默认配置项

必须在配置文件中注册app–> rest_framework

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'one.apps.OneConfig',
    # 这个重要
    'rest_framework',
]

【 1 】源码解析

# 构造方式
from rest_framework.response import Response
def __init__(self, data=None, status=None,
                 template_name=None, headers=None,
                 exception=False, content_type=None):
# 参数说明    
	- data:你要返回的数据,字典
	- status:返回的状态码,默认是200,使用如常量用更加见名知意
        from rest_framework import status
            HTTP_100_CONTINUE = 100
            HTTP_200_OK = 200
            HTTP_201_CREATED = 201
            。。。。。		
	- template_name 渲染的模板名字(自定制模板),不需要了解
	- headers:响应头,可以往响应头放东西,就是一个字典
	- content_type:响应的编码格式,application/json和text/html;

    
#### 重要的###
data
status
headers
        
        
# 补充:报django-session表不存在
	-前端带了 sessionid---》到后端,它就会django-session中取数据,取不到就报错了

data数据不是render处理之后的数据,只需传递python的内建类型数据即可,REST framework会使用renderer渲染器处理data

data不能是复杂结构的数据,如Django的模型类对象,对于这样的数据我们可以使用Serializer序列化器序列化处理后(转为了Python字典类型)再传递给data参数。

  • Response对象属性

# response.data
	传给response对象的序列化后,但尚未render处理的数据
# response.status_code
	状态码的数字
# response.content
	经过render处理后的响应数据

【 2 】响应格式

优先用 视图类的—》项目配置文件—》drf内置的(两个都支持)

# 浏览器响应成浏览器的格式,postman响应成json格式,通过配置实现的(默认配置)
#不管是postman还是浏览器,都返回json格式数据
# drf有默认的配置文件---》先从项目的setting中找,找不到,采用默认的
# drf的配置信息,先从自己类中找--》项目的setting中找---》默认的找
-局部使用:对某个视图类有效
    -在视图类中写如下
    from rest_framework.renderers import JSONRenderer
    renderer_classes=[JSONRenderer,]
    
-全局使用:全局的视图类,所有请求,都有效
-在项目的setting.py中加入如下
    REST_FRAMEWORK = {
        'DEFAULT_RENDERER_CLASSES': (  # 默认响应渲染类
            'rest_framework.renderers.JSONRenderer',  # json渲染器
            'rest_framework.renderers.BrowsableAPIRenderer',  # 浏览API渲染器,如果注释这一行使用浏览器打开接口的时候就不会有模板渲染
        )
    }
  • 'rest_framework.renderers.JSONRenderer':这个渲染器类负责将数据渲染为 JSON 格式。
    • 当 API 视图返回一个响应时,如果没有指定特定的渲染器,Django REST Framework 就会默认使用这个渲染器将数据转换为 JSON 格式,并将其作为 HTTP 响应的内容返回给客户端。
  • 'rest_framework.renderers.BrowsableAPIRenderer':这个渲染器类负责将 API 数据渲染为可浏览的 HTML 格式,以便在浏览器中进行浏览和交互。
    • 它提供了一个友好的界面,可以浏览 API 的端点、查看请求和响应的数据,并且还支持用户在浏览器中进行测试和调试 API。
# 控制解析格式使用
# 响应对象
# ------------------------------
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer
class ReqsuetView(APIView):
    # 第一种方法
    # 设置解析器类列表,包括 JSONRenderer, BrowsableAPIRenderer

    renderer_classes = [JSONRenderer, BrowsableAPIRenderer]

    def post(self,request):

        print(request.data)
        FILES = request.FILES
        print(FILES)
        return Response({"code":'200',"msg":request.data})

    def get(self,request):
        res = Response(data={},status=201,headers={'name':'jingyi'})
        print(res.status_text)
        return res

【 三 】基于APIView的两个视图基类(重要)

【 0 】前言

# 两个视图基类
	APIView
    GenericAPIView

APIView—>之前我们是一直在用来实现接口的增删改查—》drf提供的最顶层的父类—》以后所有视图类,都继承自它

GenericAPIView(就是小弟)–》继承自APIView–》封装

【2】GenericAPIView的使用方法

  • GenericAPIView

    • 如果要写publish的5个接口,所有代码不变,只需要改两个类属性即可

    • #  # many=True 表示序列化器将处理多个对象而不是单个对象。
      
      
    • '''
      GenericAPIView:
      两个类属性:queryset和serializer_class
      '''
      # 三个方法:
      self.get_object()  # 获取单个数据  
      self.get_serializer()   # 序列化类
      self.get_queryset()  # 获取多个数据
      

【1】GenericAPIView + 序列化类 + Response

from rest_framework.generics import GenericAPIView

# GenericAPIView + 序列化类 + Response
class BookView(GenericAPIView):
    #   继承GenericAPIView的写法
    # 在类中,写两个类属性:所有数据,序列化类

    # 拿到所有的数据 (拿多条数据)
    queryset = Book.objects.all()
    # 序列化类
    serializer_class = BookSerializer

    # 查询所有图书
    def get(self, request):
        # 使用get_queryset方法获取所有数据,而不是使用self.get_queryset() 属性获取
        res_list = self.get_queryset()
        # 使用序列化类 -- > 直接使用方法: self.serializer_class()
        serializer = self.serializer_class(instance=res_list,many=True)
        return Response({"code":200,"msg":"查询成功!!!","results": serializer.data})

    def post(self, request):
        # 使用序列化类 -- > 直接使用方法: self.serializer_class()
        res_data = self.serializer_class(data=request.data)
        if res_data.is_valid():
            # 验证过后的数据
            print(res_data.validated_data)
            # 保存数据
            res_data.save()
            return Response({"code":200,"msg":"添加成功!!!","results": res_data.data}, status=status.HTTP_201_CREATED)
        else:
            return Response({'code': 404, 'msg': res_data.errors})


class BookDetailView(GenericAPIView):
    # 拿到所有的数据 (拿多条数据)
    queryset = Book.objects.all()
    # 序列化类
    serializer_class = BookSerializer

    # 查询单个数据
    def get(self, request, pk):
        # self.get_object() 这个方法就是拿到单个对象
        res_list = self.get_object()
        print(res_list)
        # 剑来
        res_data = self.serializer_class(instance=res_list)
        return Response({"code":200,"msg":"查询成功!!!","results": res_data.data})


    # 子序列化版本
    def put(self, request, pk):
        # instance 就是序列化的  res_data就是反序列化的
        obj = self.get_object()
        res_data = self.serializer_class(data=request.data, instance=obj)
        if res_data.is_valid():
            # 验证过后的数据
            print(res_data.validated_data)
            # 保存数据
            res_data.save()
            return Response({'code': 200, "msg": res_data.data})
        else:
            return Response({'code': 404, 'msg': res_data.errors})

    def delete(self, request, pk):
        self.get_object().delete()

        return Response({'code': 200, 'msg': '删除成功!!!'}, status=status.HTTP_404_NOT_FOUND)

【2】5个视图扩展类 + GenericAPIView + 序列化类 + Response

5个视图扩展类,不是视图类—> 要使用就必须要GenericAPIView 跟 + 视图扩展类

# 5个视图扩展类 + GenericAPIView + 序列化类 + Response

# 5个视图扩展类,不是视图类---> 要使用就必须要GenericAPIView 跟 + 视图扩展类
# 他们是可以进行组合的

from rest_framework.mixins import CreateModelMixin, RetrieveModelMixin, DestroyModelMixin, ListModelMixin, \
    UpdateModelMixin


class BookView(GenericAPIView, ListModelMixin, CreateModelMixin):
    #   继承GenericAPIView的写法
    # 在类中,写两个类属性:所有数据,序列化类

    # 拿到所有的数据 (拿多条数据)
    queryset = Book.objects.all()
    # 序列化类
    serializer_class = BookSerializer

    # 查询所有图书
    def get(self, request):
        # # ListModelMixin(查询所有) 的list
        return super().list(request)

    def post(self, request):
        # CreateModelMixin(添加) 的create
        return super().create(request)


class BookDetailView(GenericAPIView, DestroyModelMixin, RetrieveModelMixin, UpdateModelMixin):
    # 拿到所有的数据 (拿多条数据)
    queryset = Book.objects.all()
    # 序列化类
    serializer_class = BookSerializer

    # 查询单个数据
    def get(self, request, *args, **kwargs):
        # RetrieveModelMixin(查找单个) retrieve
        return super().retrieve(request, *args, **kwargs)

    # 子序列化版本
    def put(self, request, *args, **kwargs):
        # UpdateModelMixin(更改) update
        return super().update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        # DestroyModelMixin(更改) destroy
        return super().destroy(request, *args, **kwargs)

​ 使用 CreateModelMixinRetrieveModelMixinUpdateModelMixinDestroyModelMixinListModelMixin 这些 mixin 类时,你不需要自己实现这些方法,它们已经为你提供了常见的 CRUD 操作的实现。下面是每个 mixin 类的主要方法和作用:

  1. CreateModelMixin:
    • create(request, *args, **kwargs): 处理 HTTP POST 请求,用于创建新的模型实例。它会从请求数据中反序列化出新的模型实例,并保存到数据库中。
  2. RetrieveModelMixin:
    • retrieve(request, *args, **kwargs): 处理 HTTP GET 请求,用于检索特定的模型实例。它会从 URL 参数中获取主键值,并从数据库中检索对应的模型实例。
  3. UpdateModelMixin:
    • update(request, *args, **kwargs): 处理 HTTP PUT 请求,用于更新现有的模型实例。它会从请求数据中反序列化出更新后的模型实例,并保存到数据库中。
  4. DestroyModelMixin:
    • destroy(request, *args, **kwargs): 处理 HTTP DELETE 请求,用于删除现有的模型实例。它会从 URL 参数中获取主键值,并从数据库中删除对应的模型实例。
  5. ListModelMixin:
    • list(request, *args, **kwargs): 处理 HTTP GET 请求,用于检索多个模型实例。它会从数据库中检索出符合条件的一组模型实例,并将其序列化为 JSON 数据返回给客户端。

这些方法在对应的视图类中被调用,并且已经实现了大部分的逻辑,因此你只需要将 mixin 类与 GenericAPIView 结合使用,并在视图中设置好相应的属性(如 querysetserializer_class),即可完成相应的 CRUD 操作。

【3】9个视图子类

​ 视图子类它们的功能和灵活性。它们提供了不同的操作,允许你对 API 进行增删改查等各种操作,极大地简化了开发过程。你可以根据需要选择合适的视图子类来构建你的 API,从而快速、高效地开发出功能完善的应用程序。

九个视图子类其实就是组合的视图类

  • CreateAPIView
    用于仅创建新模型实例对象的视图
    提供 POST 请求方式
    依赖:GenericAPIView, CreateModelMixin
  • ListAPIView
    用于仅只读模型实例对象集合数据的视图
    提供 GET 请求方式
    依赖:GenericAPIView, ListModelMixin
  • RetrieveAPIView
    用于仅只读单个模型实例对象的视图
    提供 GET 请求方式
    依赖:GenericAPIView, RetrieveModelMixin
  • DestroyAPIView
    用于仅删除单个模型实例对象的视图
    提供 DELETE 请求方式
    依赖:GenericAPIView, DestroyModelMixin
  • UpdateAPIView
    用于仅对已有模型实例进行修改的视图
    提供 PUTPATCH 请求方式
    依赖:GenericAPIView, UpdateModelMixin
  • ListCreateAPIView
    用于对模型实例对象集读取和写入的视图
    提供 GETPOST 请求方式
    依赖:GenericAPIView, ListModelMixin, CreateModelMixin
  • RetrieveUpdateAPIView
    用于对单个模型实例的读取和更新的视图
    提供 GETPUTPATCH 请求方式
    依赖:GenericAPIView, RetrieveModelMixin, UpdateModelMixin
  • RetrieveDestroyAPIView
    用于对单个模型实例的读取和删除的视图
    提供 GETDELETE 请求方式
    依赖:GenericAPIView, RetrieveModelMixin, DestroyModelMixin
  • RetrieveUpdateDestroyAPIView
    用于对单个模型实例的读取、更新和删除的视图
    提供 GETPUTPATCHDELETE 请求方式
    依赖:GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin
# #         CreateAPIView     添加
# #         RetrieveAPIView   查找单个
# #         DestroyAPIView    删除
# #         ListAPIView       查找全部
# #         UpdateAPIView     更改

# #         ListCreateAPIView      查找全部并添加
# #         RetrieveDestroyAPIView     查找并删除
# #         RetrieveUpdateDestroyAPIView     查找、更新后删除
# #         RetrieveUpdateAPIView     查找并更新

使用方法

  • urls.py

from django.urls import path
from one.views import ReqsuetView, BookView  ,BookDetailView

urlpatterns = [
    path('books/', BookView.as_view()),
    path('books/<int:pk>/', BookDetailView.as_view()),
]
  • 序列化类

万金油

from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from one.models import Book


#
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'
from rest_framework.generics import CreateAPIView, RetrieveAPIView, DestroyAPIView, ListAPIView, UpdateAPIView
from rest_framework.generics import ListCreateAPIView,RetrieveDestroyAPIView,RetrieveUpdateDestroyAPIView,RetrieveUpdateAPIView

from one.models import Book
from one.serial import BookSerializer


class BookView(ListCreateAPIView):
    # 查询所有和新增一条接口
    queryset = Book.objects.all()
    serializer_class = BookSerializer


class BookDetailView(RetrieveUpdateDestroyAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

上面用到的实际上就是ListCreateAPIView(查询所有创建)RetrieveUpdateDestroyAPIView(查找单个更改删除)

class BookDetailView(RetrieveUpdateDestroyAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    # get delete put --> 不改继承的类,限制只能发送get请求
    # 用到哪个写哪个就行了
    http_method_names = [
        "get",
    ]

image-20240415222128527

  • 8
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值