【 一 】drf之请求
请求对象Request
【 0 】前言
在 Python 中,通常通过 request
对象来处理 HTTP 请求,尤其是在 web 开发中,比如使用 Django、Flask 等框架时会经常接触到这个对象。request
对象是框架提供的,用于封装客户端发送的 HTTP 请求,并提供了访问请求头、请求体、请求参数等信息的方法和属性。
对于 Django 框架而言,request
对象是 Django 中视图函数的一个参数,表示客户端发送的 HTTP 请求。下面是一些常用的 request
对象的属性和方法:
- 属性:
request.method
:HTTP 请求方法,如 GET、POST、PUT、DELETE 等。request.GET
:包含 GET 请求参数的 QueryDict 对象。request.POST
:包含 POST 请求参数的 QueryDict 对象。request.FILES
:包含文件上传的文件对象的字典。request.path
:请求的路径部分,不包括域名和查询参数。request.headers
:请求头部信息,以字典形式保存。
- 方法:
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、MultiPartParserparser_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.FILESprint(FILES)# < MultiValueDict: {'myssda': [ < TemporaryUploadedFile: ffmpeg.dll(application / x - msdownload) >]} >return Response({"code":'200',"msg":request.data})
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 statusHTTP_100_CONTINUE = 100HTTP_200_OK = 200HTTP_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.data传给response对象的序列化后,但尚未render处理的数据
# response.status_code状态码的数字
# response.content经过render处理后的响应数据
【 2 】响应格式
优先用 视图类的—》项目配置文件—》drf内置的(两个都支持)
# 浏览器响应成浏览器的格式,postman响应成json格式,通过配置实现的(默认配置)
#不管是postman还是浏览器,都返回json格式数据
# drf有默认的配置文件---》先从项目的setting中找,找不到,采用默认的
# drf的配置信息,先从自己类中找--》项目的setting中找---》默认的找
-局部使用:对某个视图类有效-在视图类中写如下from rest_framework.renderers import JSONRendererrenderer_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, BrowsableAPIRendererrenderer_classes = [JSONRenderer, BrowsableAPIRenderer]def post(self,request):print(request.data)FILES = request.FILESprint(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 】前言
# 两个视图基类APIViewGenericAPIView
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, \UpdateModelMixinclass BookView(GenericAPIView, ListModelMixin, CreateModelMixin):# 继承GenericAPIView的写法# 在类中,写两个类属性:所有数据,序列化类# 拿到所有的数据 (拿多条数据)queryset = Book.objects.all()# 序列化类serializer_class = BookSerializer# 查询所有图书def get(self, request):# # ListModelMixin(查询所有) 的listreturn super().list(request)def post(self, request):# CreateModelMixin(添加) 的createreturn super().create(request)class BookDetailView(GenericAPIView, DestroyModelMixin, RetrieveModelMixin, UpdateModelMixin):# 拿到所有的数据 (拿多条数据)queryset = Book.objects.all()# 序列化类serializer_class = BookSerializer# 查询单个数据def get(self, request, *args, **kwargs):# RetrieveModelMixin(查找单个) retrievereturn super().retrieve(request, *args, **kwargs)# 子序列化版本def put(self, request, *args, **kwargs):# UpdateModelMixin(更改) updatereturn super().update(request, *args, **kwargs)def delete(self, request, *args, **kwargs):# DestroyModelMixin(更改) destroyreturn super().destroy(request, *args, **kwargs)
使用 CreateModelMixin
、RetrieveModelMixin
、UpdateModelMixin
、DestroyModelMixin
和 ListModelMixin
这些 mixin 类时,你不需要自己实现这些方法,它们已经为你提供了常见的 CRUD 操作的实现。下面是每个 mixin 类的主要方法和作用:
CreateModelMixin
:create(request, *args, **kwargs)
: 处理 HTTP POST 请求,用于创建新的模型实例。它会从请求数据中反序列化出新的模型实例,并保存到数据库中。
RetrieveModelMixin
:retrieve(request, *args, **kwargs)
: 处理 HTTP GET 请求,用于检索特定的模型实例。它会从 URL 参数中获取主键值,并从数据库中检索对应的模型实例。
UpdateModelMixin
:update(request, *args, **kwargs)
: 处理 HTTP PUT 请求,用于更新现有的模型实例。它会从请求数据中反序列化出更新后的模型实例,并保存到数据库中。
DestroyModelMixin
:destroy(request, *args, **kwargs)
: 处理 HTTP DELETE 请求,用于删除现有的模型实例。它会从 URL 参数中获取主键值,并从数据库中删除对应的模型实例。
ListModelMixin
:list(request, *args, **kwargs)
: 处理 HTTP GET 请求,用于检索多个模型实例。它会从数据库中检索出符合条件的一组模型实例,并将其序列化为 JSON 数据返回给客户端。
这些方法在对应的视图类中被调用,并且已经实现了大部分的逻辑,因此你只需要将 mixin 类与 GenericAPIView
结合使用,并在视图中设置好相应的属性(如 queryset
或 serializer_class
),即可完成相应的 CRUD 操作。
【3】9个视图子类
视图子类它们的功能和灵活性。它们提供了不同的操作,允许你对 API 进行增删改查等各种操作,极大地简化了开发过程。你可以根据需要选择合适的视图子类来构建你的 API,从而快速、高效地开发出功能完善的应用程序。
九个视图子类其实就是组合的视图类
CreateAPIView
用于仅创建新模型实例对象的视图
提供POST
请求方式
依赖:GenericAPIView
,CreateModelMixin
ListAPIView
用于仅只读模型实例对象集合数据的视图
提供GET
请求方式
依赖:GenericAPIView
,ListModelMixin
RetrieveAPIView
用于仅只读单个模型实例对象的视图
提供GET
请求方式
依赖:GenericAPIView
,RetrieveModelMixin
DestroyAPIView
用于仅删除单个模型实例对象的视图
提供DELETE
请求方式
依赖:GenericAPIView
,DestroyModelMixin
UpdateAPIView
用于仅对已有模型实例进行修改的视图
提供PUT
和PATCH
请求方式
依赖:GenericAPIView
,UpdateModelMixin
ListCreateAPIView
用于对模型实例对象集读取和写入的视图
提供GET
和POST
请求方式
依赖:GenericAPIView
,ListModelMixin
,CreateModelMixin
RetrieveUpdateAPIView
用于对单个模型实例的读取和更新的视图
提供GET
、PUT
和PATCH
请求方式
依赖:GenericAPIView
,RetrieveModelMixin
,UpdateModelMixin
RetrieveDestroyAPIView
用于对单个模型实例的读取和删除的视图
提供GET
和DELETE
请求方式
依赖:GenericAPIView
,RetrieveModelMixin
,DestroyModelMixin
RetrieveUpdateDestroyAPIView
用于对单个模型实例的读取、更新和删除的视图
提供GET
、PUT
、PATCH
和DELETE
请求方式
依赖:GenericAPIView
,RetrieveModelMixin
,UpdateModelMixin
,DestroyModelMixin
# # CreateAPIView 添加
# # RetrieveAPIView 查找单个
# # DestroyAPIView 删除
# # ListAPIView 查找全部
# # UpdateAPIView 更改# # ListCreateAPIView 查找全部并添加
# # RetrieveDestroyAPIView 查找并删除
# # RetrieveUpdateDestroyAPIView 查找、更新后删除
# # RetrieveUpdateAPIView 查找并更新
使用方法
from django.urls import path
from one.views import ReqsuetView, BookView ,BookDetailViewurlpatterns = [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 = Bookfields = '__all__'
from rest_framework.generics import CreateAPIView, RetrieveAPIView, DestroyAPIView, ListAPIView, UpdateAPIView
from rest_framework.generics import ListCreateAPIView,RetrieveDestroyAPIView,RetrieveUpdateDestroyAPIView,RetrieveUpdateAPIViewfrom one.models import Book
from one.serial import BookSerializerclass BookView(ListCreateAPIView):# 查询所有和新增一条接口queryset = Book.objects.all()serializer_class = BookSerializerclass 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",]