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})
总结
可以发现,通过一步一步封装,我们所需要书写的代码越来越少
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!