DRF视图开发restful接口

yodragon 2026-03-01 21 阅读

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 = CourseSerializer

4. 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参数的前面

已经是最后一篇了

搜索

文章归档

广告位招租

广告位招租