作者&好友:Laoqi
drf
传入视图的request
不再是Django默认的HttpRequest对象,而是drf
提供的拓展了HttpRequest 类的Request
类的对象。
drf提供了Parser解析器,在接收到请求之后会根据Content-Type指明的请求数据类型(json、表单等)将请求数据进行解析,解析为类字典<QueryDict>
对象保存到Request
对象之中。
Request对象的数据是根据前端发送数据的格式进行解析之后的结果。不论前端发送的是那种格式的数据,我们都可以使用统一的方式读取数据。
常用属性:
.data
request.data
?返回解析之后的请求体数据。类似于Django中标准的request.POST
和?request.FILES
属性,但提供如下特性:
1 包含了解析之后的文件和非文件数据
2 包含了对POST、PUT、PATCH请求方式解析后的数据
3 利用了REST framework的parsers解析器,不仅支持表单类型数据,也支持JSON数据
.query_params
request.query_params
与Django标准的request.GET
相同,只是更换了更正确的名称而已。
drf
提供了一个响应类Response
,使用该类构造响应对象时,响应的具体数据内容会被转换(render渲染)成符合前端需求的类型。
drf
提供了Renderer
?渲染器,用来根据请求头中的Accept
(接收数据类型声明)来自动转换响应数据到对应格式。如果前端请求中未进行Accept声明,则会采用默认方式处理响应数据,我们可以通过配置来修改默认响应格式。
可以在rest_framework.settings
查找所有的drf默认配置项。其中配置响应格式的配置项为:
在局部配置使用,即只对某一个视图类配置生效。在视图类中加入以下代码:
from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer
renderer_classes=[JSONRenderer,] #配置使用json渲染器
# renderer_classes=[BrowsableAPIRenderer,] # 配置使用浏览API渲染器
在全局配置使用,即对所有的视图类、所有的请求都生效。在setting.py
中加入以下代码:
REST_FRAMEWORK = {
‘DEFAULT_RENDERER_CLASSES‘: ( # 默认响应渲染类
‘rest_framework.renderers.JSONRenderer‘, # json渲染器
‘rest_framework.renderers.BrowsableAPIRenderer‘, # 浏览API渲染器
)
}
找到drf
中的Response类,可以获知其有以下代码:
class Response(SimpleTemplateResponse):
def __init__(self, data=None, status=None,
template_name=None, headers=None,
exception=False, content_type=None):
...
则Response对象的构造方式为:
Response(data, status=None, template_name=None, headers=None, content_type=None)
其中data数据不要是render处理之后的数据,只需要传递你需要返回的数据。drf
会自动使用renderer
渲染器处理该数据。
参数说明:
data
: 为响应准备的序列化处理后的数据;status
: 状态码,默认200;template_name
: 模板名称,如果使用HTMLRenderer
时需指明;headers
: 用于存放响应头信息的字典;content_type
: 响应数据的Content-Type,通常此参数无需传递,REST framework会根据前端所需类型数据来设置该参数。为了方便设置状态码,drf
在rest_framework.status
模块中提供了常用状态码常量。
信息告知 - 1xx
HTTP_100_CONTINUE = 100
HTTP_101_SWITCHING_PROTOCOLS = 101
成功 - 2xx
HTTP_200_OK = 200
HTTP_201_CREATED = 201
HTTP_202_ACCEPTED = 202
HTTP_203_NON_AUTHORITATIVE_INFORMATION = 203
HTTP_204_NO_CONTENT = 204
HTTP_205_RESET_CONTENT = 205
HTTP_206_PARTIAL_CONTENT = 206
HTTP_207_MULTI_STATUS = 207
HTTP_208_ALREADY_REPORTED = 208
HTTP_226_IM_USED = 226
重定向 - 3xx
HTTP_300_MULTIPLE_CHOICES = 300
HTTP_301_MOVED_PERMANENTLY = 301
HTTP_302_FOUND = 302
HTTP_303_SEE_OTHER = 303
HTTP_304_NOT_MODIFIED = 304
HTTP_305_USE_PROXY = 305
HTTP_306_RESERVED = 306
HTTP_307_TEMPORARY_REDIRECT = 307
HTTP_308_PERMANENT_REDIRECT = 308
客户端错误 - 4xx
HTTP_400_BAD_REQUEST = 400
HTTP_401_UNAUTHORIZED = 401
HTTP_402_PAYMENT_REQUIRED = 402
HTTP_403_FORBIDDEN = 403
HTTP_404_NOT_FOUND = 404
HTTP_405_METHOD_NOT_ALLOWED = 405
HTTP_406_NOT_ACCEPTABLE = 406
HTTP_407_PROXY_AUTHENTICATION_REQUIRED = 407
HTTP_408_REQUEST_TIMEOUT = 408
HTTP_409_CONFLICT = 409
HTTP_410_GONE = 410
HTTP_411_LENGTH_REQUIRED = 411
HTTP_412_PRECONDITION_FAILED = 412
HTTP_413_REQUEST_ENTITY_TOO_LARGE = 413
HTTP_414_REQUEST_URI_TOO_LONG = 414
HTTP_415_UNSUPPORTED_MEDIA_TYPE = 415
HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE = 416
HTTP_417_EXPECTATION_FAILED = 417
HTTP_422_UNPROCESSABLE_ENTITY = 422
HTTP_423_LOCKED = 423
HTTP_424_FAILED_DEPENDENCY = 424
HTTP_426_UPGRADE_REQUIRED = 426
HTTP_428_PRECONDITION_REQUIRED = 428
HTTP_429_TOO_MANY_REQUESTS = 429
HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE = 431
HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS = 451
服务器错误- 5xx
HTTP_500_INTERNAL_SERVER_ERROR = 500
HTTP_501_NOT_IMPLEMENTED = 501
HTTP_502_BAD_GATEWAY = 502
HTTP_503_SERVICE_UNAVAILABLE = 503
HTTP_504_GATEWAY_TIMEOUT = 504
HTTP_505_HTTP_VERSION_NOT_SUPPORTED = 505
HTTP_506_VARIANT_ALSO_NEGOTIATES = 506
HTTP_507_INSUFFICIENT_STORAGE = 507
HTTP_508_LOOP_DETECTED = 508
HTTP_509_BANDWIDTH_LIMIT_EXCEEDED = 509
HTTP_510_NOT_EXTENDED = 510
HTTP_511_NETWORK_AUTHENTICATION_REQUIRED = 511
drf
的提供的视图的主要作用有:
它还提供了许多的视图基类和拓展类,用于简化视图的编写。
APIView
是drf
提供的所有视图的基类,继承自Django的View
父类。
APIView
与View
的不同之处在于:
Request
对象,而不是Django的HttpRequeset
对象;Response
对象,视图会为响应数据设置(render)符合前端要求的格式;APIException
异常都会被捕获到,并且处理成合适的响应信息;在APIView
中仍以常规的类视图定义方法来实现get() 、post() 或者其他请求方式的方法。例如使用APIView简单的实现五个增删查改的API接口。
在models.py
创建数据模型类:
from django.db import models
class Book(models.Model):
name=models.CharField(max_length=32)
price=models.DecimalField(max_digits=5,decimal_places=2)
publish=models.CharField(max_length=32)
在urls.py
中创建路由匹配:
from django.urls import path,re_path
from app01 import views
urlpatterns = [
path(‘books/‘, views.BookView.as_view()),
re_path(‘books/(?P<pk>\d+)‘, views.BookDetailView.as_view()),
]
在ser.py
中创建ModelSerializer
类:
from rest_framework import serializers
from app01.models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model=Book
fields=‘__all__‘
在views.py
中基于APIView创建视图类
from rest_framework.views import APIView
from app01.models import Book
from app01.ser import BookSerializer
class BookView(APIView):
def get(self,request):
book_list=Book.objects.all()
book_ser=BookSerializer(book_list,many=True)
return Response(book_ser.data)
def post(self,request):
book_ser = BookSerializer(data=request.data)
if book_ser.is_valid():
book_ser.save()
return Response(book_ser.data)
else:
return Response({‘status‘:101,‘msg‘:‘校验失败‘})
class BookDetailView(APIView):
def get(self, request, pk):
book = Book.objects.all().filter(pk=pk).first()
book_ser = BookSerializer(book)
return Response(book_ser.data)
def put(self, request, pk):
book = Book.objects.all().filter(pk=pk).first()
book_ser = BookSerializer(instance=book,data=request.data)
if book_ser.is_valid():
book_ser.save()
return Response(book_ser.data)
else:
return Response({‘status‘: 101, ‘msg‘: ‘校验失败‘})
def delete(self,request, pk):
ret=Book.objects.filter(pk=pk).delete()
return Response({‘status‘: 100, ‘msg‘: ‘删除成功‘})
导入:
from rest_framework.generics import GenericAPIView
继承关系如下:
GenericAPIView
继承自APIVIew
,主要增加了操作序列化器和数据库查询的方法,作用是为下面Mixin扩展类的执行提供方法支持。通常在使用时,可搭配一个或多个Mixin扩展类。
提供的关于序列化器使用的属性与方法
属性:serializer_class
?指明视图使用的序列化器
方法:
get_serializer_class(self)
: 当出现一个视图类中调用多个序列化器时,那么可以通过条件判断在get_serializer_class方法中通过返回不同的序列化器类名就可以让视图方法执行不同的序列化器对象了。返回序列化器类,默认返回serializer_class
,可以重写。
get_serializer(self, *args, **kwargs)
:返回序列化器对象,主要用来提供给Mixin扩展类使用,如果我们在视图中想要获取序列化器对象,也可以直接调用此方法。
注意:
该方法在提供序列化器对象的时候,会向序列化器对象的context属性补充三个数据:request、format、view,这三个数据对象可以在定义序列化器时使用。
-request 当前视图的请求对象
-view 当前请求的类视图对象
-format 当前请求期望返回的数据格式
提供的关于数据库查询的属性与方法
属性:queryset
? 指明使用的数据查询集
方法:
get_queryset(self)
:返回视图使用的查询集,主要用来提供给Mixin扩展类使用,是列表视图与详情视图获取数据的基础,默认返回queryset
属性,可以重写
get_object(self)
:返回详情视图所需的模型类数据对象,主要用来提供给Mixin扩展类使用。在试图中可以调用该方法获取详情信息的模型类对象。若详情访问的模型类对象不存在,会返回404。该方法会默认使用APIView提供的check_object_permissions方法检查当前对象是否有权限被访问。
示例:使用GenericAPIView
将之前创建的接口进行改写:
urls.py
:
from django.urls import path,re_path
from app01 import views
urlpatterns = [
# 使用GenericAPIView重写的
path(‘books2/‘, views.Book2View.as_view()),
re_path(‘books2/(?P<pk>\d+)‘, views.Book2DetailView.as_view()),
]
views.py
:
class Book2View(GenericAPIView):
# queryset要传queryset对象,查询了所有的图书
# serializer_class使用哪个序列化类来序列化这堆数据
queryset = Book.objects
# queryset=Book.objects.all()
serializer_class = BookSerializer
def get(self, request):
book_list = self.get_queryset()
book_ser = self.get_serializer(book_list, many=True)
return Response(book_ser.data)
def post(self, request):
book_ser = self.get_serializer(data=request.data)
if book_ser.is_valid():
book_ser.save()
return Response(book_ser.data)
else:
return Response({‘status‘: 101, ‘msg‘: ‘校验失败‘})
class Book2DetailView(GenericAPIView):
queryset = Book.objects
serializer_class = BookSerializer
def get(self, request, pk):
book = self.get_object()
book_ser = self.get_serializer(book)
return Response(book_ser.data)
def put(self, request, pk):
book = self.get_object()
book_ser = self.get_serializer(instance=book, data=request.data)
if book_ser.is_valid():
book_ser.save()
return Response(book_ser.data)
else:
return Response({‘status‘: 101, ‘msg‘: ‘校验失败‘})
def delete(self, request, pk):
ret = self.get_object().delete()
return Response({‘status‘: 100, ‘msg‘: ‘删除成功‘})
作用:
? 提供了几种后端视图(对数据资源进行曾删改查)处理流程的实现,如果需要编写的视图属于这五种,则视图可以通过继承相应的扩展类来复用代码,减少自己编写的代码量。
? 这五个扩展类需要搭配GenericAPIView
父类,因为五个扩展类的实现需要调用GenericAPIView
提供的序列化器与数据库查询的方法。
导入:
from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelMixin
from rest_framework.mixins import DestroyModelMixin, RetrieveModelMixin
ListModelMixin
:列表视图扩展类,提供list(request, *args, **kwargs)
方法快速实现列表视图,返回200状态码。该Mixin的list方法会对数据进行过滤和分页。
RetrieveModelMixin
:详情视图扩展类,提供retrieve(request, *args, **kwargs)
方法,可以快速实现返回一个存在的数据对象。如果存在,返回200, 否则返回404。
CreateModelMixin
:创建视图扩展类,提供create(request, *args, **kwargs)
方法快速实现创建资源的视图,成功返回201状态码。如果序列化器对前端发送的数据验证失败,返回400错误。
UpdateModelMixin
:更新视图扩展类,提供update(request, *args, **kwargs)
方法,可以快速实现更新一个存在的数据对象。同时也提供partial_update(request, *args, **kwargs)
方法,可以实现局部更新。
成功返回200,序列化器校验数据失败时,返回400错误。
DestroyModelMixin
: 删除视图扩展类,提供destroy(request, *args, **kwargs)
方法,可以快速实现删除一个存在的数据对象。成功返回204,不存在返回404。
使用示例,基于GenericAPIView和5个视图拓展类改写接口:
urls.py
:
from django.urls import path,re_path
from app01 import views
urlpatterns = [
# 使用GenericAPIView+5 个视图扩展类
path(‘books3/‘, views.Book3View.as_view()),
re_path(‘books3/(?P<pk>\d+)‘, views.Book3DetailView.as_view()),
]
views.py
:
from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin, RetrieveModelMixin
class Book3View(GenericAPIView, ListModelMixin, CreateModelMixin):
queryset = Book.objects
serializer_class = BookSerializer
def get(self, request):
return self.list(request)
def post(self, request):
return self.create(request)
class Book3DetailView(GenericAPIView, RetrieveModelMixin, DestroyModelMixin, UpdateModelMixin):
queryset = Book.objects
serializer_class = BookSerializer
def get(self, request, pk):
return self.retrieve(request, pk)
def put(self, request, pk):
return self.update(request, pk)
def delete(self, request, pk):
return self.destroy(request, pk)
导入:
from rest_framework.generics import CreateAPIView, ListAPIView, UpdateAPIView, RetrieveAPIView, DestroyAPIView, ListCreateAPIView, RetrieveUpdateDestroyAPIView, RetrieveDestroyAPIView, RetrieveUpdateAPIView
这些视图子类分别部分提供了get
post
put
patch
delete
方法,继承自GenericAPIView
及其拓展类。
应用示例:
urls.py
:
from django.urls import path,re_path
from app01 import views
urlpatterns = [
path(‘books4/‘, views.Book4View.as_view()),
re_path(‘books4/(?P<pk>\d+)‘, views.Book4DetailView.as_view()),
]
views.py
:
from rest_framework.generics import CreateAPIView, ListAPIView, UpdateAPIView, RetrieveAPIView, DestroyAPIView, ListCreateAPIView, RetrieveUpdateDestroyAPIView, RetrieveDestroyAPIView, RetrieveUpdateAPIView
# class Book4View(ListAPIView,CreateAPIView): #获取所有,新增一个
class Book4View(ListCreateAPIView): # 获取所有,新增一个
queryset = Book.objects
serializer_class = BookSerializer
# class Book4DetailView(UpdateAPIView,RetrieveAPIView,DestroyAPIView):
class Book4DetailView(RetrieveUpdateDestroyAPIView):
queryset = Book.objects
serializer_class = BookSerializer
使用视图集ViewSet
,可以将一系列逻辑相关的动作放到一个类中:
list()
提供一组数据retrieve()
提供单个数据create()
创建数据update()
保存数据destory()
删除数据ViewSet
视图集类不再实现get()
、post()
等方法,而是实现动作 action
如 list() 、create() 等。
视图集只在使用as_view()
方法的时候,才会将action
动作与具体请求方式对应上。
ViewSet
: 继承自APIView与ViewSetMixin,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。ViewSet主要通过继承ViewSetMixin来实现在调用as_view()时传入字典(如{‘get’:’list’})的映射处理工作。在ViewSet中,没有提供任何动作action方法,需要我们自己实现action方法。GenericViewSet
:使用ViewSet通常并不方便,因为list、retrieve、create、update、destory等方法都需要自己编写,而这些方法与前面讲过的Mixin扩展类提供的方法同名,所以我们可以通过继承Mixin扩展类来复用这些方法而无需自己编写。但是Mixin扩展类依赖与GenericAPIView,所以还需要继承GenericAPIView 。GenericViewSet就帮助我们完成了这样的继承工作,继承自GenericAPIView与ViewSetMixin,在实现了调用as_view()时传入字典(如{‘get‘:‘list‘}
)的映射处理工作的同时,还提供了GenericAPIView提供的基础方法,可以直接搭配Mixin扩展类使用。ModelViewSet
:继承自GenericViewSet
,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。ReadOnlyModelViewSet
:继承自GenericViewSet
,同时包括了ListModelMixin、RetrieveModelMixin。在视图集中,我们可以通过action对象属性来获取当前请求视图集时的action动作是哪个。除了默认的方法动作外,还可以添加自定义动作。
示例:
from rest_framework.viewsets import ModelViewSet,ReadOnlyModelViewSet
class StudentModelViewSet(ModelViewSet):
queryset = Student.objects.all()
serializer_class = StudentModelSerializer
def login(self,request):
"""学生登录功能"""
return Response({"message":"登录成功"})
url的定义:
urlpatterns = [
path("students/", views.StudentModelViewSet.as_view({"get": "list", "post": "create"})),
re_path("students/(?P<pk>\d+)/",
views.StudentModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),
path("stu/login/",views.StudentModelViewSet.as_view({"get":"login"}))
]
视图集应用改写接口示例:
urls.py
:
urlpatterns = [
# 使用ModelViewSet编写5个接口
path(‘books5/‘, views.Book5View.as_view(actions={‘get‘: ‘list‘, ‘post‘: ‘create‘})),
# 当路径匹配,又是get请求,会执行Book5View的list方法
re_path(‘books5/(?P<pk>\d+)‘,
views.Book5View.as_view(actions={‘get‘: ‘retrieve‘, ‘put‘: ‘update‘, ‘delete‘: ‘destroy‘})),
]
views.py
:
# 使用ModelViewSet编写5个接口
from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
class Book5View(ModelViewSet):
queryset = Book.objects
serializer_class = BookSerializer
# class Book5View(ReadOnlyModelViewSet): # 2个接口,获取一条,和获取所有两个
# queryset = Book.objects
# serializer_class = BookSerializer
GenericAPIView的视图子类继承关系:
视图集:
原文:https://www.cnblogs.com/ssgeek/p/13270187.html