Django REST framwork 提供的视图的主要作用:
我们可以使用View来编写CBV格式的视图,APIView继承了view,封装了request,提供了更多的功能
drf中实际上还有很多别的视图类,增加了操作序列化器和数据库查询的方法,并且进一步精简代码,十分方便
rest_framework.views.APIView
APIView
是REST framework提供的所有视图的基类,继承自Django的View
父类。
APIView
与View
的不同之处在于:
Request
对象,而不是Django的HttpRequeset
对象;Response
对象,视图会为响应数据设置(render)符合前端要求的格式;APIException
异常都会被捕获到,并且处理成合适的响应信息;在APIView
中仍以常规的类视图定义方法来实现get() 、post() 或者其他请求方式的方法。在上一篇博客中已经包含了使用序列器和APIView
下面是对图书表操作的例子
# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from app01.models import Book
from app01.ser import BookSerializer
# 基于APIView写的
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):
# 路由中有名分组,获取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‘: ‘删除成功‘})
# models.py
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)
#ser.py
class BookSerializer(serializers.ModelSerializer):
# 模型类序列化器
class Meta:
model=Book
fields=‘__all__‘
# urls.py
path(‘books/‘, views.BookView.as_view()),
re_path(‘books/(?P<pk>\d+)‘, views.BookDetailView.as_view()),
导入GenericAPIView,看一看源码
可以看到,继承了APIView,并且自带两个属性,queryset
和serializer_class
,其中,queryset就是使用APIview时候,用数据库查询到的对象,serializer_class就是序列化器类,于是我们把这两个东西传进去
# urls.py
urlpatterns = [
url(r‘^admin/‘, admin.site.urls),
url(r‘^book/‘, views.Book1View.as_view()),
url(‘books2/(?P<pk>\d+)/‘, views.Book1DetailView.as_view())
]
# views.py
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from hwk01.models import Book
from hwk01.ser import BookSerializer
# Create your views here.
class Book1View(GenericAPIView):
# queryset要传queryset对象,查询了所有的图书
queryset = Book.objects
# 这里不传queryset对象也没关系,基类中会帮你.all()获取成queryset对象
serializer_class = BookSerializer
# 传入序列化器类
def get(self, request):
book_list = self.get_queryset()
# 获得视图使用的查询集,就是Book.object.all()
book_ser = self.get_serializer(book_list, many=True)
# 就是BookSerializer(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 Book1DetailView(GenericAPIView):
queryset = Book.objects
serializer_class = BookSerializer
def get(self, request, pk):
book = self.get_object()
# get_object和get_queryset的区别,一个获取一个,一个获取全部
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可以发现,跟使用APIView没有什么区别,只是把模型数据和序列化器在类里面传入了。因此,我们要对操作别的基类的时候,可以只是换掉视图的名字,模型类和序列化器,其他代码复制过去就可以直接用了。
当然这么多重复的代码,drf也提供了扩展类来进一步精简
from rest_framework.mixins import ListModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin
# 从这里导入
这些接口中自带了我们上面写的查询全部,新增,删除,更改等等操作,还自带了过滤器和分页器,下面直接上使用方法
# urls.py
url(r‘^book2/‘, views.Book2View.as_view()),
url(‘books2/(?P<pk>\d+)/‘, views.Book2DetailView.as_view())
# views.py
class Book2View(GenericAPIView,ListModelMixin,CreateModelMixin):
queryset=Book.objects
serializer_class = BookSerializer
def get(self,request):
return self.list(request)
# 获取全部数据,使用list
def post(self,request):
return self.create(request)
# 新增一个数据,用create
class Book2DetailView(GenericAPIView,RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin):
queryset = Book.objects
serializer_class = BookSerializer
def get(self, request,pk):
return self.retrieve(request,pk)
# 查询单个数据:retrieve,获取id值,自动查询
def put(self, request,pk):
return self.update(request,pk)
# 更新单个数据,update
def delete(self,request,pk):
return self.destroy(request,pk)
# 删除单个数据,destroy
相比起只使用GenericAPI,代码又精简了一些
比起上面mixin类更加恐怖的精简,只要写几行代码导入模型和序列化器,url配置一下就能实现上面的操作了
from rest_framework.generics import GenericAPIView,CreateAPIView,RetrieveAPIView,DestroyAPIView,UpdateAPIView,ListAPIView
# 在导入GenericAPIView的地方导入
# urls.py
url(r‘^book3/‘, views.Book3View.as_view()),
url(‘books3/(?P<pk>\d+)/‘, views.Book3DetailView.as_view())
# views.py
class Book3View(ListAPIView,CreateAPIView):
# 不需要pk值的视图,查询全部和新增:List,Create
queryset = Book.objects
serializer_class = BookSerializer
class Book3DetailView(RetrieveAPIView,DestroyAPIView,UpdateAPIView):
# 需要pk的视图,Retrieve,Destroy,Update
queryset = Book.objects
serializer_class = BookSerializer
复杂的接口仅需要几行就写完了,甚至还可以更加精简!
两两想通过类里面继承的类可以写在一起
... import ListCreateAPIView
class Book3View(ListCreateAPIView):
queryset = Book.objects
serializer_class = BookSerializer
这个类重写了as_view方法
暂时只学到在路由中设置方法,支持根据请求触发指定的方法
# views.py
from rest_framework.viewsets import ViewSetMixin
class Book6View(ViewSetMixin,APIView): #一定要放在APIVIew前
def get_all_book(self,request):
print("xxxx")
book_list = Book.objects.all()
book_ser = BookSerializer(book_list, many=True)
return Response(book_ser.data)
# urls.py
path(‘books6/‘, views.Book6View.as_view(actions={‘get‘: ‘get_all_book‘})),
# 动作写在action中,接收get请求时,触发后面的方法名
原文:https://www.cnblogs.com/telecasterfanclub/p/13268901.html