一、请求对象

1. Request objects

​ REST framework 传入视图的request对象不再是Django默认的HttpRequest对象,而是REST framework提供的扩展了HttpRequest类的Request类的对象。REST framework 提供了Parser解析器,在接收到请求后会自动根据Content-Type指明的请求数据类型(如JSON、表单等)将请求数据进行parse解析,解析为类字典对象保存到Request对象中

​ Request对象的数据是自动根据前端发送数据的格式进行解析之后的结果。**无论前端发送的哪种格式的数据,我们都可以以统一的方式读取数据。

2. 常用属性

2.1 request.data

返回解析之后的请求体数据。类似于Django中标准的request.POSTrequest.FILES属性,但提供如下特性:

  • 包含了解析之后的文件和非文件数据
  • 包含了对POST、PUT、PATCH请求方式解析后的数据
  • 利用了REST framework的parsers解析器,不仅支持表单类型数据,也支持JSON数据

2.2 request.query_params

与Django标准的request.GET相同,只是更换了更正确的名称而已。

2.3. 总结

  • GET请求:如果想获取GET请求的所有参数,使用request.query_params即可
  • POST请求:使用request.data就可以处理传入的json请求,或者其他格式请求。

3. 使用示例

from django.http import HttpResponse
from rest_framework.renderers import JSONRenderer

from quickstart.models import BookInfo
from quickstart.serializers import BookInfoSerializer
from rest_framework.decorators import api_view


class JSONResponse(HttpResponse):
    """
    将内容渲染成JSON的HttpResponse
    """

    def __init__(self, data, **kwargs):
        content = JSONRenderer().render(data)
        kwargs['content_type'] = 'application/json'
        super(JSONResponse, self).__init__(content, **kwargs)


# 使用函数修饰器修改GET和POST请求
@api_view(['GET', 'POST'])
def BookInfoView(request):
    """
    列出所有的book信息,或创建一个新book。
    """
    if request.method == 'GET':
        print(request.query_params)
        books = BookInfo.objects.all()
        serializer = BookInfoSerializer(books, many=True)
        return JSONResponse(serializer.data)

    elif request.method == 'POST':
        # book = JSONParser().parse(request)
        # serializer = BookInfoSerializer(data=book)
        # 使用request.data自动将请求内容数据部分处理
        print(request.data)
        serializer = BookInfoSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return JSONResponse(serializer.data, status=201)
        return JSONResponse(serializer.errors, status=400)


@api_view(['GET', 'PUT', 'DELETE'])
def BookInfoDetailView(request, book_id):
    """
    获取,更新或删除一个指定ID的book。
    """
    try:
        book = BookInfo.objects.get(pk=book_id)
    except BookInfo.DoesNotExist:
        return JSONResponse(status=404)

    if request.method == 'GET':
        serializer = BookInfoSerializer(book)
        return JSONResponse(serializer.data)

    elif request.method == 'PUT':
        # data = JSONParser().parse(request)
        # serializer = BookInfoSerializer(book, data=data)
        # 使用request.data自动将请求内容数据部分处理
        serializer = BookInfoSerializer(book, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return JSONResponse(serializer.data)
        return JSONResponse(serializer.errors, status=400)

    elif request.method == 'DELETE':
        book.delete()
        return JSONResponse(status=204)

二、响应对象

1. Response objects

​ REST framework提供了一个响应类Response,使用该类构造响应对象时,响应的具体数据内容会被转换(render渲染)成符合前端需求的类型。

2. 常用属性

2.1 构造方式

Response(data, status=None, template_name=None, headers=None, content_type=None)

2.2 参数说明:

  • data: 为响应准备的序列化处理后的数据(序列化器序列化处理后的数据)
  • status: 状态码,默认200;
  • template_name: 模板名称,如果使用HTMLRenderer 时需指明;
  • headers: 用于存放响应头信息的字典;
  • content_type: 响应数据的Content-Type,通常此参数无需传递,REST framework会根据前端所需类型数据来设置该参数。

2.3 状态码

为了方便设置状态码,REST framewrok在rest_framework.status模块中提供了常用状态码常量。

3. 示例

不再需要JSONResponse类,所有响应通过response即可 使用命名状态代码,使得响应意义更加明显

from rest_framework import status
from quickstart.models import BookInfo
from quickstart.serializers import BookInfoSerializer
from rest_framework.decorators import api_view
from rest_framework.response import Response


# 使用函数修饰器修改GET和POST请求
@api_view(['GET', 'POST'])
def BookInfoView(request):
    """
    列出所有的book信息,或创建一个新book。
    """
    if request.method == 'GET':
        books = BookInfo.objects.all()
        serializer = BookInfoSerializer(books, many=True)
        return Response(serializer.data)

    elif request.method == 'POST':
        serializer = BookInfoSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


@api_view(['GET', 'PUT', 'DELETE'])
def BookInfoDetailView(request, book_id):
    """
    获取,更新或删除一个指定ID的book。
    """
    try:
        book = BookInfo.objects.get(pk=book_id)
    except BookInfo.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    if request.method == 'GET':
        serializer = BookInfoSerializer(book)
        return Response(serializer.data)

    elif request.method == 'PUT':
        serializer = BookInfoSerializer(book, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    elif request.method == 'DELETE':
        book.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

REST framework 提供了众多的通用视图基类与扩展类,以简化视图的编写。

三、视图的继承关系

DRF.png

四、一级视图(APIView)

1. APIView

  1. APIView是REST framework提供的所有视图的基类,继承自Django的View父类。
  2. APIViewView的不同之处在于:
  • 传入到视图方法中的是REST framework的Request对象,而不是Django的HttpRequeset对象;
  • 视图方法可以返回REST framework的Response对象,视图会为响应数据设置(render)符合前端要求的格式;
  • 任何APIException异常都会被捕获到,并且处理成合适的响应信息;
  • 在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制。
  1. 支持定义的属性:
  • authentication_classes 列表或元祖,身份认证类
  • permissoin_classes 列表或元祖,权限检查类
  • throttle_classes 列表或元祖,流量控制类
  1. APIView中仍以常规的类视图定义方法来实现get() 、post() 或者其他请求方式的方法。

2. 使用APIView

  • 修改view.py文件,将根视图重写为基于类的视图。

BookInfoDetailView中每个函数都需要获取指定id的对象,抽离成类方法

from django.http import Http404
from rest_framework import status
from rest_framework.views import APIView

from quickstart.models import BookInfo
from quickstart.serializers import BookInfoSerializer
from rest_framework.response import Response


class BookInfoView(APIView):
    """
    列出所有的book信息,或创建一个新book。
    """

    def get(self, request):
        books = BookInfo.objects.all()
        serializer = BookInfoSerializer(books, many=True)
        return Response(serializer.data)

    def post(self, request):
        serializer = BookInfoSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class BookInfoDetailView(APIView):
    """
    获取,更新或删除一个指定ID的book。
    """

    def get_object(self, book_id):
        try:
            return BookInfo.objects.get(pk=book_id)
        except BookInfo.DoesNotExist:
            raise Http404

    def get(self, request, book_id):
        book = self.get_object(book_id)
        serializer = BookInfoSerializer(book)
        return Response(serializer.data)

    def put(self, request, book_id):
        book = self.get_object(book_id)
        serializer = BookInfoSerializer(book, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, book_id):
        book = self.get_object(book_id)
        book.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)
  1. 修改路由
from django.urls import path
from quickstart import views

urlpatterns = [
    path('books/', views.BookInfoView.as_view()),
    path('books/<int:book_id>', views.BookInfoDetailView.as_view())
]

五、二级视图GenericApiView

1. GenericApiView

继承自APIVIew,增加了对于列表视图和详情视图可能用到的通用支持方法。通常使用时,可搭配一个或多个Mixin扩展类。

2. 支持定义的属性:

  • 列表视图与详情视图通用:
  • queryset 列表视图的查询集
  • serializer_class 视图使用的序列化器
  • 列表视图使用:
  • pagination_class 分页控制类
  • filter_backends 过滤控制后端
  • 详情页视图使用:
  • lookup_field 查询单一数据库对象时使用的条件字段,默认为'pk'
  • lookup_url_kwarg 查询单一数据时URL中的参数关键字名称,默认与look_field相同

3. 提供的方法(列表视图与详情视图通用)

  • get_queryset(self) 返回视图使用的查询集,是列表视图与详情视图获取数据的基础,默认返回queryset属性,可以重写,例如:
def get_queryset(self):
    user = self.request.user
    return user.accounts.all()
  • get_serializer_class(self) 返回序列化器类,默认返回serializer_class,可以重写,例如:
def get_serializer_class(self):
    if self.request.user.is_staff:
        return FullAccountSerializer
    return BasicAccountSerializer
  • get_serializer(self, _args, _kwargs) 返回序列化器对象,被其他视图或扩展类使用,如果我们在视图中想要获取序列化器对象,可以直接调用此方法。 注意,在提供序列化器对象的时候,REST framework会向对象的context属性补充三个数据:request、format、view,这三个数据对象可以在定义序列化器时使用。*

  • get_object(self) 返回详情视图所需的模型类数据对象,默认使用lookup_field参数来过滤queryset。 在试图中可以调用该方法获取详情信息的模型类对象。 若详情访问的模型类对象不存在,会返回404。 该方法会默认使用APIView提供的check_object_permissions方法检查当前对象是否有权限被访问。

4. 使用示例

from rest_framework import status
from quickstart.models import BookInfo
from quickstart.serializers import BookInfoSerializer
from rest_framework.response import Response
from rest_framework import generics


class BookInfoView(generics.GenericAPIView):
    """
    列出所有的book信息,或创建一个新book。
    """
    # 通用的属性(查询集,序列化器)
    # 原来一个类只能对一个对象和序列化器进行操作,改写完成后根据需求,填写不同的对象和序列化器即可
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer

    def get(self, request):
        # books = self.queryset
        books = self.get_queryset()
        # serializer = self.serializer_class(books, many=True)
        # serializer = self.get_serializer_class()(books, many=True)
        serializer = self.get_serializer(books, many=True)
        return Response(serializer.data)

    def post(self, request):
        serializer = self.get_serializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class BookInfoDetailView(generics.GenericAPIView):
    """
    获取,更新或删除一个指定ID的book。
    """
    # 通用属性
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer
    # 默认传入id名称为pk,可以自定义其他名称
    # lookup_url_kwarg = "book_id"

    def get(self, request, pk):
        book = self.get_object()  # 根据book_id到queryset中取出指定对象,传入id名称必须为pk
        serializer = self.get_serializer(book)
        return Response(serializer.data)

    def put(self, request, pk):
        book = self.get_object()
        serializer = self.get_serializer(book, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk):
        book = self.get_object()
        book.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

六、混合视图(mixins)

1. 简介

  1. 使用基于类视图的最大优势之一是它可以轻松地创建可复用的行为。
  2. 我们使用的创建/获取/更新/删除操作和我们创建的任何基于模型的API视图非常相似。这些常见的行为是在REST框架的mixin类中实现的。
  3. mixins提供的类
类名称 提供方法 功能
ListModelMixin list 查询所有数据
CreateModelMixin create 创建单个对象
RetrieveModelMixin retrieve 获取单个对象
UpdateModelMixin update 更新单个对象
DestroyModelMixin destroy 删除单个对象

2. 示例

from quickstart.models import BookInfo
from quickstart.serializers import BookInfoSerializer
from rest_framework import generics
from rest_framework import mixins


class BookInfoView(mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView):
    """
    列出所有的book信息,或创建一个新book。
    """
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer

    def get(self, request):
        return self.list(request)

    def post(self, request):
        return self.create(request)


class BookInfoDetailView(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin,
                         generics.GenericAPIView):
    """
    获取,更新或删除一个指定ID的book。
    """
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer

    def get(self, request, pk):
        return self.retrieve(request)

    def put(self, request, pk):
        return self.update(request)

    def delete(self, request, pk):
        return self.destroy(request)

七、三级视图generics

如果没有大量自定义的行为, 可以使用通用视图(三级视图)来简化我们的views.py模块。

1. 常见的通用视图总结

类名称 父类 提供方法 作用
CreateAPIView GenericAPIView CreateModelMixin post 创建单个对象
ListAPIView GenericAPIView ListModelMixin get 查询所有的数据
RetrieveAPIView GenericAPIView RetrieveModelMixin get 获取单个对象
DestroyAPIView GenericAPIView DestroyModelMixin delete 删除单个对象
UpdateAPIView GenericAPIView UpdateModelMixin put 更新单个对象

2. 使用示例

from quickstart.models import BookInfo
from quickstart.serializers import BookInfoSerializer
from rest_framework import generics


class BookInfoView(generics.ListCreateAPIView):
    """
    列出所有的book信息,或创建一个新book。
    """
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer


class BookInfoDetailView(generics.RetrieveUpdateDestroyAPIView):
    """
    获取,更新或删除一个指定ID的book。
    """
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer

八、视图集

1. 特点:

  • 可以将一组相关的操作, 放在一个类中进行完成
  • 不提供get,post方法, 使用retrieve, create方法来替代
  • 可以将标准的请求方式(get,post,put,delete), 和mixin中的方法做映射

2. 常见的视图集父类

类名称 父类 作用
ViewSet APIView ViewSetMixin 可以做路由映射
GenericViewSet GenericAPIView ViewSetMixin 可以做路由映射,可以使用二级视图三个属性,三个方法
ModelViewSet GenericAPIView 5个mixin类 所有的增删改查功能,可以使用二级视图三个属性,三个方法
ReadOnlyModelViewSet GenericAPIView RetrieveModelMixin ListModelMixin 获取单个,所有数据,可以使用二级视图三个属性,三个方法

3. 示例

3.1 ViewSet

  • view.ps
from rest_framework.generics import get_object_or_404
from rest_framework.response import Response
from quickstart.models import BookInfo
from quickstart.serializers import BookInfoSerializer
from rest_framework import viewsets
class BookInfoViewSet(viewsets.ViewSet):
    """
    获取所有图书和单个图书信息
    """
    def list(self, request):
        queryset = BookInfo.objects.all()
        serializer = BookInfoSerializer(queryset, many=True)
        return Response(serializer.data)
    def retrieve(self, request, pk=None):
        queryset = BookInfo.objects.all()
        book = get_object_or_404(queryset, pk=pk)
        serializer = BookInfoSerializer(book)
        return Response(serializer.data)
  • urls.py
from django.urls import path
from quickstart import views

urlpatterns = [
    path('books/', views.BookInfoViewSet.as_view({'get': 'list'})),
    path('books/<int:pk>', views.BookInfoViewSet.as_view({'get': 'retrieve'}))
]

3.2 ModelViewSet

  • view.ps
from quickstart.models import BookInfo
from quickstart.serializers import BookInfoSerializer
from rest_framework import viewsets


class BookInfoModelViewSet(viewsets.ModelViewSet):
    """
    获取所有图书和单个图书信息的增删改查
    """
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer
  • urls.py
from django.urls import path
from quickstart import views

urlpatterns = [
    path('books/', views.BookInfoModelViewSet.as_view({'get': 'list', 'post': 'create'})),
    path('books/<int:pk>',
         views.BookInfoModelViewSet.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'}))
]

3.3 ReadOnlyModelViewSet

  • view.ps
from quickstart.models import BookInfo
from quickstart.serializers import BookInfoSerializer
from rest_framework import viewsets


class BookInfoReadOnlyModelViewSet(viewsets.ReadOnlyModelViewSet):
    """
    获取所有图书和单个图书信息
    """
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer
  • urls.py
from django.urls import path
from quickstart import views

urlpatterns = [
    path('books/', views.BookInfoReadOnlyModelViewSet.as_view({'get': 'list'})),
    path('books/<int:pk>', views.BookInfoReadOnlyModelViewSet.as_view({'get': 'retrieve'}))
]

九、附加action动作

1. action

  1. 添加自定义动作需要使用rest_framework.decorators.action装饰器。
  2. 以action装饰器装饰的方法名会作为action动作名,与list、retrieve等同。
  3. action装饰器可以接收两个参数:
  • methods: 该action支持的请求方式,列表传递
  • detail: 表示是action中要处理的是否是视图资源的对象(即是否通过url路径获取主键)

True 表示使用通过URL获取的主键对应的数据对象 False 表示不使用URL获取主键

2. 示例

  • view.py
from rest_framework.response import Response
from quickstart.models import BookInfo
from quickstart.serializers import BookInfoSerializer
from rest_framework import viewsets
from rest_framework.decorators import action


class BookInfoModelViewSet(viewsets.ModelViewSet):
    """
    获取所有图书和单个图书信息的增删改查
    """
    # 标准动作的 viewset
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer

    # detail为False 表示不需要处理具体的对象
    @action(methods=['get'], detail=False)
    def latest(self, request):
        """
        返回最新图书信息
        """
        # 获取指定对象
        book = BookInfo.objects.latest('id')
        # 创建序列化器对象
        serializer = self.get_serializer(book)
        # 返回响应
        return Response(serializer.data)

    # detail为True 表示对pk对应的对象进行处理
    @action(methods=['put'], detail=True)
    def read(self, request, pk):
        """
        修改图书阅读量
        """
        # 获取指定pk的对象
        book = self.get_object()
        # 修改对象属性
        book.read = request.data.get('read')
        # 数据入库
        book.save()
        # 创建序列化器对象
        serializer = self.get_serializer(book)
        # 返回响应
        return Response(serializer.data)
  • urls.py
from django.urls import path
from quickstart import views

urlpatterns = [
    path('books/', views.BookInfoModelViewSet.as_view({'get': 'list', 'post': 'create'})),
    path('books/latest', views.BookInfoModelViewSet.as_view({'get': 'latest'})),
    path('books/<int:pk>',
         views.BookInfoModelViewSet.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
    path('books/<int:pk>/read', views.BookInfoModelViewSet.as_view({'put': 'read'}))
]
0 子项 · 1 次浏览 · 2026-09-24