1. 函数式编程 Function Based View(函数视图)
1.1. Django 自带的写法
#Django默认编写api接口
@csrf_exempt #from django.views.decoratirs.csrf import csrf_exempt
def course_list(request):
course_dict = {
"name": "课程名称",
"introduction": "课程介绍",
"price": 0.11
}
if request.method == 'GET':
return JsonResponse(course_dict)
if request.method == 'POST':
course = json.loads(request.body.decode('utf-8'))
return JsonResponse(course)1.2. DRF写法
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from .models import Course
from .serializers import CourseSerializer
from rest_framework.views import APIView #
"""函数式编程"""
@api_view(['GET','POST'])
def course_list(request):
"""
获取所有的课程信息或者新增一个课程
:param request:
:return:
"""
if request.method == 'GET':
CourserSerializer = CourseSerializer(
instance=Course.objects.all(),
many=True,
context={'request':request}
)#序列化多个对象
return Response(CourserSerializer.data,status = status.HTTP_200_OK) #返回序列化之后的数据,返回成功状态码
elif request.method == 'POST':
#对数据进行校验和反序列化
serializer = CourseSerializer(data=request.data)#如果是部分更新,使用partial=True属性
if serializer.is_valid():
serializer.save(teacher = request.user)
return Response(serializer.data,status = status.HTTP_201_CREATED) #返回数据和创建成功状态码
else: #没有通过校验
return Response(serializer.errors,status = status.HTTP_400_BAD_REQUEST)#返回校验不通过状态码
@api_view(['GET','PUT','DELETE']) #把普通的DJango视图函数,变为DRF视图函数
def course_detail(request,pk):
"""
获取,更新,删除一个课程
:param request:
:param pk: #主键
:return:
"""
try:
#尝试获取数据
course = Course.objects.get(pk=pk)
except Course.DoesNotExist:
#自定义返回错误信息
return Response(data={"msg":"没有课程信息"},status=status.HTTP_404_NOT_FOUND)
else:
if request.method == 'GET':
#这里的实例代指要被实例化的对象
serializer = CourseSerializer(instance=course)
return Response(serializer.data,status = status.HTTP_200_OK)
elif request.method == 'PUT': #更新
#这是是指要用data这条数据去更新course这条实例
serializer = CourseSerializer(instance=course,data = request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data,status = status.HTTP_200_OK)
elif request.method == 'DELETE': #删除
course.delete()
return Response(status = status.HTTP_204_NO_CONTENT)注意:@api_view(['GET','POST']) 的作用是:把普通 Django 函数视图转换成 DRF 的 API 视图,并限制允许的 HTTP 请求方法。
2. 类视图 Classed Based View
2.1. django自带的写法
#Django CBV编写API接口
#对不同的请求用不同的函数处理
@method_decorator(csrf_exempt,name='dispatch') #from django.utils.decorators import method_decorator
class CourseList(View):
course_dict = {
"name": "课程名称",
"introduction": "课程介绍",
"price": 0.11
}
def get(self,request):
return JsonResponse(course_dict)
def post(self,request):
course = json.loads(request.body.decode('utf-8'))
return JsonResponse(course)2.2. DRF写法
class CourseList(APIView):
def get(self, request):
queryset = Course.objects.all()
s= CourseSerializer(instance = queryset, many=True) #实例化对象,查询使用all,就算只有一条数据也不影响
return Response(s.data,status = status.HTTP_200_OK)
def post(self,request):
s = CourseSerializer(data=request.data)
if s.is_valid():
s.save(teacher =self.request.user) #数据校验没有问题就保存,由于teacher这个字段只读,所以要在save方法里保存
print(type(request.data),type(s.data))
return Response(s.data,status = status.HTTP_201_CREATED)
return Response(s.errors,status = status.HTTP_400_BAD_REQUEST)
class CourseDetail(APIView):
@staticmethod #不涉及到属性,request请求,self的话可以使用静态方法,可以在类外也可以在类内使用
def get_object(pk):
"""
:param pk:
:return:
"""
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)
if not obj:
return Response(data={"msg":"没有此课程信息"},status = status.HTTP_404_NOT_FOUND)
else:
s = CourseSerializer(instance=obj)
return Response(s.data,status = status.HTTP_200_OK)
def put(self, request, pk):
obj = self.get_object(pk)
if not obj:
return Response(data={"msg": "没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
else:
s = CourseSerializer(instance = obj, data = request.data)
if s.is_valid():
s.save()
return Response(s.data,status = status.HTTP_200_OK)
return Response(s.errors,status = status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk):
obj = self.get_object(pk)
if not obj:
return Response(data={"msg": "没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
else:
obj.delete()
return Response(status=status.HTTP_204_NO_CONTENT)注意:如果函数内部不涉及类属性,request请求,还有类本身,那么@staticmetho可以把类试图函数编程普通的函数,在类的内外都可以调用,静态方法
3. 通用类视图 Generic Classed Based View
DRF提供的半自动接口生成器,只需要指定queryset和seriallizer,就能自动完成常见的增删改查等接口
from rest_framework import generics
注意利用钩子函数重写CRUD逻辑
3.1. e.g
#通用类试图函数
from rest_framework import generics #导入类
'''通用类试图 Generic Class Based View'''
#自带get和post,可以获取数据或者创建数据
class GCourseList(generics.ListCreateAPIView):#ListCreateAPIView查看所有课程信息或者新建一个课程信息
queryset = Course.objects.all().order_by('id')#告诉数据从哪里来
serializer_class = CourseSerializer #告诉数据用哪个序列化器
def perform_create(self, serializer): #重写perform_create函数创建新用户
serializer.save(teacher = self.request.user)
#自带获取单个数据,更新,删除功能
class GCourseDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Course.objects.all().order_by('id')
serializer_class = CourseSerializer4. DRF视图集viewsets
4.1. 类实现
'''视图集viewsets'''
from rest_framework import viewsets
class CourseViewSet(viewsets.ModelViewSet):
queryset = Course.objects.all().order_by('id')
serializer_class = CourseSerializer
def perform_create(self, serializer):
serializer.save(teacher = self.request.user)ModelViewSet相当于一个List,Create,Retrieve,Update,partial_update(局部修改),Destory方法的总和,自动实现了CURD
4.2. 配置url
4.2.1. 普通配置
#DRF视图集
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","delete":"destroy","patch":"partial_update"}
),name='viewsets-detail'),由于ViewSet不是一个普通的视图,需要手动映射,当某个请求访问这个URL的时候,调用什么方法
4.2.2. router配置URL
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(prefix="viewsets",viewset=views.CourseViewSet,basename="courses")
urlpatterns = [
path("",include(router.urls)),
]
这里的path里面的router参数可以拼接在主路由后面,register里面的prefix参数的前面