rest_framework框架视图

视图:restframework中提供了两个视图基类,APIView和GenericAPIView

那么这两个视图基类有什么区别呢,本质上是差不多,但是GenericAPIView在APIView的基础上封装了一层,

这使得我们在实现相同功能的情况下书写的代码更少



1 基于APIView写接口

# url.py
from django.urls import path,re_path
from app01 import views
urlpatterns = [
	path('api/book/',views.BookView.as_view()),
	re_path(r'^api/book/(?P<pk>\d+)',views.BookDetailView.as_view())
]


# models.py
class Book(models.Model):
	name=models.CharField(max_length=32)
	price=models.CharField(max_length=32)



# ser.py
from rest_framework import serializers
from app01.models import Book

# Book模型类的序列化器
# 这里我们为了方便不书写任何校验规则
class BookSerializer(serializers.ModelSerializer):
	class Meta:
		model=Book
		fields='__all__'




# view.py
from rest_framework.views import APIView
from rest_framework.response import Response
from app01.models import Book
from app01.ser import BookSerializer
class BookView(APIView):
	def get(self,reqeust):
		book_list=Book.objects.all()
		book_ser=BookSerializer(instance=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({'status':200,'msg':'success'})
		return Response({'status':101,'msg':'error'})


class BookDetailView(APIView):
	def get(self,request,pk):
		book=Book.objects.filter(pk=pk).first()
		book_ser=BookSerializer(instance=book)
		return Response(book_ser.data)

	def put(self,request,pk):
		book=Book.objects.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)
		return Response({'status':101,'msg':'error'})

	def delete(self,request,pk):
		Book.objects.filter(pk=pk).delete()
		return Response({'status':200,'msg':'success'})

可以发现这样书写非常繁琐,当我们有多张表需要操作是很麻烦


2 基于GenericAPIView写接口

继承关系:GenerciAPIView继承了APIView
在APIV的基础上拓展了一些方法,比如获取对象queryset对象,和获取序列化器的方法
所以我们在书写继承GenericAPIView接口类是要书写 queryset = 模型类.objects.all() | serializer_class = 序列化器

接口示例

# url.py
from django.urls import path,re_path
from app01 import views
urlpatterns = [
	path('api/book/',views.BookView.as_view()),
	re_path(r'^api/book/(?P<pk>\d+)',views.BookDetailView.as_view())
]



# models.py
class Book(models.Model):
	name=models.CharField(max_length=32)
	price=models.CharField(max_length=32)




# ser.py
from rest_framework import serializers
from app01.models import Book

# Book模型类的序列化器
# 这里我们为了方便不书写任何校验规则
class BookSerializer(serializers.ModelSerializer):
	class Meta:
		model=Book
		fields='__all__'





# views.py
from rest_framework.generics import GenericAPIView
from app01.models import Book
from app01.ser import BookSerializer
from rest_framework.response import Response
class BookView(GenericAPIView):
	queryset=Book.objects.all()
	serializer_class = BookSerializer
	def get(self,request):
		book_list=self.get_queryset()
		book_ser=self.get_serializer(instance=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({'status':200,'msg':'success'})
		return Response({'status':101,'msg':'error'})



class BookDetailView(GenericAPIView):
	queryset = Book.objects.all()
	serializer_class = BookSerializer
	def get(self,request,pk):
		book=self.get_queryset().filter(pk=pk).first()
		book_ser=self.get_serializer(instance=book)
		return Response(book_ser.data)

	def put(self,request,pk):
		book=self.get_queryset().filter(pk=pk).first()
		book_ser=self.get_serializer(instance=book,data=request.data)
		if book_ser.is_valid():
			book_ser.save()
			return Response(book_ser.data)
		return Response({'status':101,'msg':'error'})

	def delete(self,request,pk):
		self.get_queryset().filter(pk=pk).delete()
		return Response({'status':200,'msg':'success'})

2.1 基于GenericAPIView的5个视图扩展类写的接口

点击查看代码
# views.py
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import CreateModelMixin,DestroyModelMixin,RetrieveModelMixin,ListModelMixin,UpdateModelMixin
from app01.models import Book
from app01.ser import BookSerializer


class BookView(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 BookDetailView(GenericAPIView,DestroyModelMixin,RetrieveModelMixin,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)


3 ViewSetMixin

ViewSetMixin的导入: from rest_framework.viewsets import ViewSetMixin
主要作用:我们在写视图类是,内如接受各种请求方式的函数名字是固定的,而通过ViewSetMixin就可修改视图类中的函数名称,比如:原来我们接受get请求的函数定义def get(self,request): 而通过ViewSetMixin可以自定义为def get_all_book(self,request):

3.1 ViewSetMixin的使用

# url.py
from django.urls import path,re_path
from app01 import views
urlpatterns = [
	path('api/book/',views.BookView.as_view({'get':'get_all_book'})), #需要在as_view中声明,应为ViewSetMixin重写了as_view方法
	# re_path(r'^api/book/(?P<pk>\d+)',views.BookDetailView.as_view())
]


# views.py
from rest_framework.viewsets import ViewSetMixin
from rest_framework.views import APIView
from app01.ser import BookSerializer
from app01.models import Book
from rest_framework.response import Response
class BookView(ViewSetMixin,APIView): # 继承的类第一个必须是ViewSetMixin,应为ViewSetMixin重写了as_view方法
	def get_all_book(self,request):
		book_list=Book.objects.all()
		book_ser=BookSerializer(instance=book_list,many=True)
		return Response(book_ser.data)



4 基于ModelViewSet编写接口

继承关系:modelViewSet继承了GenerciAPIView和其五个视图扩展方法

# url.py
from django.urls import path,re_path
from app01 import views
urlpatterns = [
	path('api/book/',views.BookView.as_view({'get':'list','post':'create'})),
	re_path(r'^api/book/(?P<pk>\d+)',views.BookView.as_view({'get':'retrieve','put':'update','delete':'destroy'}))
]




# views.py
from rest_framework.viewsets import ViewSetMixin,ViewSet,ModelViewSet,GenericViewSet
from rest_framework.views import APIView
from app01.ser import BookSerializer
from app01.models import Book
from rest_framework.response import Response


class BookView(ModelViewSet):
	queryset = Book.objects
	serializer_class = BookSerializer

5 分页器的使用

5.1GenericAPIView下的分页器

from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination


class MyPageNumberPagination(PageNumberPagination):
	page_size = 3  # 每页条数
	page_query_param = 'page'  # 查询第几页的key
	page_size_query_param='size'  # 每一页显示的条数
	max_page_size=5  # 每页最大显示条数



class MyLimitOffsetPagination(LimitOffsetPagination):
	page_size = 3  # 每页条数
	limit_query_param = 'limit'  # 往后拿几条
	offset_query_param = 'offset'  # 标杆
	max_limit = 5  # 每页最大几条

class MyCursorPagination(CursorPagination):
	page_size = 3  # 每页条数
	ordering = '-id'  # 排序字段
	cursor_query_param = 'cursor'  # 每一页查询的key



class BookView(ListAPIView):  # 继承GenericAPIView
	queryset = models.Book.objects.all()
	serializer_class = ser.BookSerializer
	pagination_class = MyCursorPagination  # 填写分页器对象

5.2 APIView下的分页器

class BookView(APIView):
	def get(self,request):
		book_queryset=models.Book.objects.all()  
		page_obj=MyPageNumberPagination()  # 实例化得到分页器对象
		book_list=page_obj.paginate_queryset(book_queryset,request,self)  # 过滤数据
		book_ser=ser.BookSerializer(book_list,many=True)
		next_url=page_obj.get_next_link()  # 获取下一页的url
		previous_url=page_obj.get_previous_link()  # 获取上一页的url
		return Response({'next_url':next_url,'previous_url':previous_url,'data':book_ser.data})

总结

可以发现,通过一步一步封装,我们所需要书写的代码越来越少

关系

image

posted @   mress  阅读(79)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示