标签:https first 图片 管理 不能 containe ror 写视图 前端
from django.db import models
# Create your models here.
class Book(models.Model):
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8,decimal_places=2)
publish = models.CharField(max_length=32)
def __str__(self):
return self.name
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from app01 import models
class BookModelSerializer(serializers.ModelSerializer):
class Meta():
model = models.Book
fields = ‘__all__‘
def validate_name(self,name):
if name == ‘x‘:
raise ValidationError(‘名字不能是x‘)
else:
return name
# 基于APIView的视图
from rest_framework.views import APIView
class BooksView(APIView):
def get(self,request):
books = models.Book.objects.all()
books_ser = BookModelSerializer(books,many=True)
return Response(books_ser.data)
def post(self,request):
books_ser = BookModelSerializer(data=request.data)
if books_ser.is_valid():
books_ser.save()
return Response(books_ser.data)
else:
return Response(books_ser.errors)
class BookView(APIView):
def get(self,request,pk):
book = models.Book.objects.filter(pk=pk).first()
book_ser = BookModelSerializer(book)
return Response(book_ser.data)
def put(self,request,pk):
book = models.Book.objects.filter(pk=pk).first()
book_ser = BookModelSerializer(instance=book,data=request.data)
if book_ser.is_valid():
book_ser.save()
return Response(book_ser.data)
else:
return Response(book_ser.errors)
def delete(self,request,pk):
models.Book.objects.filter(pk=pk).delete()
return Response({‘status‘:‘删除成功‘})
添加了通用的模型类 queryset = None;
通用的序列化器 serializer_class = None
与APIView相比简化了代码,通过GenericAPIView类中定义的三个方法可以方便的取数据及序列化器。其他方法书写方法基本一致
GenericAPIView源码分析
GenericAPIView继承了APIView
在GenericAPIView内部添加了通用的模型类及通用的序列化器
在视图类中:
- get_queryset() # 获取queryset对象,用于查询多条数据
queryset = self.queryset 就是自定义视图类中的queryset
- get_object() # 获取一条对象数据
源码分析待定
- get_serializer(*args, **kwargs) # 获取序列化器对象
在get_serializer(*args, **kwargs)内部调用了get_serializer_class方法,该方法返回了自定义视图类中定义的序列化类,最后在get_serializer返回了自定义序列化类的对象。
# 基于GenericAPIView的视图
from rest_framework.generics import GenericAPIView
class Books1View(GenericAPIView):
queryset = models.Book.objects.all()
serializer_class = BookModelSerializer
def get(self,request):
books_list = self.get_queryset()
books_ser = self.get_serializer(books_list,many=True)
return Response(books_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(book_ser.errors)
class Book1View(GenericAPIView):
queryset = models.Book.objects
serializer_class = BookModelSerializer
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(book_ser.errors)
def delete(self,request,pk):
self.get_object().delete()
return Response(‘删除!‘)
基于GenericAPIView类的视图类与基于APIView类的视图类除了有通用的模型类以及序列化类,其余方法基本是一致的,还是需要自己来写视图类中的方法,因此rest_framework提供了五个扩展类,帮助我们减少代码量
五个扩展类
ListModelMixin,CreateModelMixin,UpdateModelMixin,
DestroyModelMixin,RetrieveModelMixin
在该扩展类中只定义了一个list方法,该方法是获取所有数据的方法,但是在该方法内部需要获取序列化器,但是该扩展类并没有继承任何父类,因此该扩展类的对象现需要在其他父类中寻找能够找到序列化类的这样的类,刚好GenericAPIView中定义了get_serializer()方法
!
这五种扩展类提供了几种后端视图(对数据资源进行曾删改查)处理流程的实现,如果需要编写的视图属于这五种,则视图可以通过继承相应的扩展类来复用代码,减少自己编写的代码量。
ListModelMixin:
内部需要get_serializer()方法
提供list(request, *args, **kwargs)方法快速实现列表视图,返回200状态码。 该Mixin的list方法会对数据进行过滤和分页。
CreateModelMixin:
内部需要get_serializer()方法
更新数据的校验是否通过.is_valid()方法
提供create(request, *args, **kwargs)方法快速实现创建资源的视图,成功返回201状态码。 如果序列化器对前端发送的数据验证失败,返回400错误。
UpdateModelMixin:
内部需要get_serializer()方法
更新数据的校验是否通过.is_valid()方法
获取单个数据的get_object()方法
提供update(request, *args, **kwargs)方法,可以快速实现更新一个存在的数据对象。
同时也提供partial_update(request, *args, **kwargs)方法,可以实现局部更新。
成功返回200,序列化器校验数据失败时,返回400错误。
DestroyModelMixin:
获取单个数据的get_object()方法
提供destroy(request, *args, **kwargs)方法,可以快速实现删除一个存在的数据对象。
成功返回204,不存在返回404。
RetrieveModelMixin:
获取单个数据的get_object()方法
内部需要get_serializer()方法
提供retrieve(request, *args, **kwargs)方法,可以快速实现返回一个存在的数据对象。 如果存在,返回200, 否则返回404。
# 基于GenericAPIView及五个扩展类的视图
from rest_framework.mixins import ListModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin
class Books2View(GenericAPIView,ListModelMixin,CreateModelMixin):
queryset = models.Book.objects.all()
serializer_class = BookModelSerializer
def get(self,request):
return self.list(request)
def post(self,request):
return self.create(request)
class Book2View(GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
queryset = models.Book.objects
serializer_class = BookModelSerializer
def get(self,request,pk):
return self.retrieve(request)
def put(self,request,pk):
return self.update(request)
def delete(self,request,pk):
return self.destroy(request)
from rest_framework.generics import ListAPIView,UpdateAPIView,DestroyAPIView,RetrieveAPIView,CreateAPIView,RetrieveUpdateAPIView,RetrieveDestroyAPIView,RetrieveUpdateDestroyAPIView,ListCreateAPIView
每个类都同时继承了GenericAPIView以及对应的五个扩展类,每个类都实现指定接口
每个子类只能实现部分接口功能
# 获取所有书籍接口
class Books3View(ListAPIView):
queryset = models.Book.objects.all()
serializer_class = BookModelSerializer
基于GenericAPIView及五个扩展类的视图中d代码量相较于继承APIView的视图缩减了很多,但是还是需要写俩个类来区分两个get方法,因此drf提供了ViewSet.使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中.
ViewSet视图集类不再实现get()、post()等方法,而是实现动作 action 如 list() 、create() 等。
视图集只在使用as_view()方法的时候,才会将action动作与具体请求方式对应上。如:
class BookInfoViewSet(viewsets.ViewSet):
def list(self, request):
books = BookInfo.objects.all()
serializer = BookInfoSerializer(books, many=True)
return Response(serializer.data)
def retrieve(self, request, pk=None):
try:
books = BookInfo.objects.get(id=pk)
except BookInfo.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
serializer = BookInfoSerializer(books)
return Response(serializer.data)
在设置路由时,我们可以如下操作:
urlpatterns = [
url(r‘^books/$‘, BookInfoViewSet.as_view({‘get‘:‘list‘}),
url(r‘^books/(?P<pk>\d+)/$‘, BookInfoViewSet.as_view({‘get‘: ‘retrieve‘})
继承自APIView
与ViewSetMixin
,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。
ViewSet主要通过继承ViewSetMixin来实现在调用as_view()时传入字典(如{‘get’:’list’})的映射处理工作。
在ViewSet中,没有提供任何动作action方法,需要我们自己实现action方法。
使用ViewSet通常并不方便,因为list、retrieve、create、update、destory等方法都需要自己编写,而这些方法与前面讲过的Mixin扩展类提供的方法同名,所以我们可以通过继承Mixin扩展类来复用这些方法而无需自己编写。但是Mixin扩展类依赖与GenericAPIView
,所以还需要继承GenericAPIView
。
GenericViewSet就帮助我们完成了这样的继承工作,继承自GenericAPIView
与ViewSetMixin
,在实现了调用as_view()时传入字典(如{‘get‘:‘list‘}
)的映射处理工作的同时,还提供了GenericAPIView
提供的基础方法,可以直接搭配Mixin扩展类使用。
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin
class Student4ViewSet(GenericViewSet,ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
queryset = Student.objects.all()
serializer_class = StudentModelSerializer
继承自GenericViewSet
,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。
from rest_framework.viewsets import ModelViewSet
class Book4View(ModelViewSet):
queryset = models.Book.objects
serializer_class = BookModelSerializer
# 基于modelviewset
re_path(r‘^books4/‘,views.Book4View.as_view({‘get‘:‘list‘,‘post‘:‘create‘})),
re_path(r‘^book4/(?P<pk>\d+)‘,views.Book4View.as_view({‘put‘:‘update‘,‘delete‘:‘destroy‘,‘get‘:‘retrieve‘})),
继承自GenericViewSet
,同时包括了ListModelMixin、RetrieveModelMixin。
# ViewSetMixin提供了as_view()方法,且配合url的actions参数,可以实现请求方式的动态指定分配
# 核心代码(所以路由中只要配置了对应关系,比如actions={‘get‘:‘list‘}),当get请求来,就会执行list方法
def view(request, *args, **kwargs):
self = cls(**initkwargs)
self.action_map = actions
for method, action in actions.items():
# method:get, action:list
handler = getattr(self, action)
# 执行完上一句,handler就变成了list的内存地址
setattr(self, method, handler)
# 执行完上一句 对象.get=list
# for循环执行完毕 对象.get:对着list 对象.post:对着create
# 等url匹配成功后,通过dispatch反射调用请求方法时,执行替换后的list,create等方法
# 基于ViewSetMixin的视图类和APIView编写接口
# 利用ViewSetMixin的as_view()方法,在url中通过actions分配请求处理的方法
# 因为仅使用APIView,所有需要自己实现接口功能
# 自定制化强,可控性高
# 代码:
# views.py
from rest_framework.viewsets import ViewSetMixin
class BookViewSetMixin(ViewSetMixin, APIView):
# ViewSetMixin一定要放在第一个父类位置,才能使用到ViewSetMixin的as_views()
def get_all_book(self,request):
book_list = models.Book.objects.all()
book_ser = ser.BookModelSerializer(book_list, many=True)
return Response(book_ser.data)
# urls.py:指定处理get请求的视图方法
url(r‘books5/$‘, views.BookViewSetMixin.as_view(actions={‘get‘: ‘get_all
标签:https first 图片 管理 不能 containe ror 写视图 前端
原文地址:https://www.cnblogs.com/Kathrine/p/13340915.html