函数式编程 Function Based View
类视图编程 Class Based View
导包
from rest_framework.views import APIView
编写views.py
代码
""" 类视图编程 Class Based View """
class CourseList(APIView):
"""
查询课程
"""
def get(self, request):
"""
:param request:
:return:
"""
queryset = Course.objects.all()
s = CourseSerializer(instance=queryset, many=True)
return Response(s.data, status=status.HTTP_200_OK)
"""
添加课程
"""
def post(self, request):
"""
:param request:
:return:
"""
s = CourseSerializer(data=request.data) # 调接口传过来的数据
if s.is_valid():
s.save(teacher=self.request.user)
# 分别是<class 'django.http.request.QueryDict'> <class 'rest_framework.utils.serializer_helpers.ReturnDict'>
print(type(request.data), type(s.data))
return Response(data=s.data, status=status.HTTP_201_CREATED)
return Response(data=s.errors, status=status.HTTP_400_BAD_REQUEST)
class CourseDetail(APIView):
"""
方便共用对象
"""
@staticmethod
def get_object(pk):
try:
return Course.objects.get(pk=pk)
except Course.DoesNotExist:
return
"""
查询课程
"""
def get(self, request, pk):
"""
:param request:
:param pk:
:return:
"""
obj = self.get_object(pk=pk)
if not obj:
return Response(data={"msg": "没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
s = CourseSerializer(instance=obj)
return Response(s.data, status=status.HTTP_200_OK)
"""
修改课程
"""
def put(self, request, pk):
"""
:param request:
:param pk:
:return:
"""
obj = self.get_object(pk=pk)
if not obj:
return Response(data={"msg": "没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
s = CourseSerializer(instance=obj, data=request.data)
if s.is_valid():
s.save()
return Response(data=s.data, status=status.HTTP_200_OK)
return Response(data=s.errors, status=status.HTTP_400_BAD_REQUEST)
"""
删除课程
"""
def delete(self, request, pk):
"""
:param request:
:param pk:
:return:
"""
obj = self.get_object(pk=pk)
if not obj:
return Response(data={"msg": "没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
obj.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
添加路由
urlpatterns = [
# FBV
path('fbv/list', views.course_list, name="fbv-list"), # name 表示网页返回显示的路由地址
path('fbv/details/<int:pk>', views.course_details, name="fbv-details"),
# Class Based View
path('cbv/list', views.CourseList.as_view(), name="cbv-list"),
path('cbv/detail/<int:pk>', views.CourseDetail.as_view(), name="cbv-detail")
]
FBV和CBV区别
- 代码风格不同,FBV更容易理解,CBV可读性更好
- CBV复用性更好
- 路由写法不同
通用类视图 GENERIC Class Based View
对类视图简单操作进行的封装
导包
from rest_framework import generics
编写views.py
代码
# 获取 添加
class GCourseList(generics.ListCreateAPIView):
# queryset名字必须为这个
queryset = Course.objects.all()
serializer_class = CourseSerializer
def perform_create(self, serializer):
serializer.save(teacher=self.request.user)
# 获取 修改 删除
class GCourseDetail(generics.RetrieveUpdateDestroyAPIView):
# queryset名字必须为这个
queryset = Course.objects.all()
serializer_class = CourseSerializer
代码非常简单,可以简单看下源码
可以看到源码其实是帮我们实现了类视图写的代码。
添加路由
urlpatterns = [
# FBV
path('fbv/list', views.course_list, name="fbv-list"), # name 表示网页返回显示的路由地址
path('fbv/details/<int:pk>', views.course_details, name="fbv-details"),
# Class Based View
path('cbv/list', views.CourseList.as_view(), name="cbv-list"),
path('cbv/detail/<int:pk>', views.CourseDetail.as_view(), name="cbv-detail"),
# Generic Class Based View
path("gcbv/list", views.GCourseList.as_view(), name="gcbv-list"),
path("gcbv/detail/<int:pk>", views.GCourseDetail.as_view(), name="gcbv-detail"),
]
可以看到返回结果已经帮我们做了分页。
视图集viewsets
导包
from rest_framework import viewsets
编写views.py
代码
"""四、 DRF的视图集viewsets"""
class CourseViewSets(viewsets.ModelViewSet):
queryset = Course.objects.all()
serializer_class = CourseSerializer
def perform_create(self, serializer):
serializer.save(teacher=self.request.user)
添加路由
两种方式
1.
# DRF viewsets
path("viewsets", views.CourseViewSet.as_view(
{"get": "list", "post": "create"}
), name="viewsets-list"),
path("viewsets/<int:pk>", views.CourseViewSet.as_view(
{"get": "retrieve", "put": "update", "patch": "partial_update", "delete": "destroy"}
), name="viewsets-detail"),
字典里面key为请求方式,value 为函数名字,可以点进去源码看函数名字
随便点进去一个看一下即可:
导入 routers包
from rest_framework.routers import DefaultRouter
初始化、注册router
router = DefaultRouter()
# prefix 相当于url前缀
router.register(prefix='viewsets', viewset=views.CourseViewSets)
配置path
path("", include(router.urls))