Django REST framework简介和举例

环境搭建

pip install djangorestframework

添加rest_framework应用

INSTALLED_APPS = [
    ...
    'rest_framework',
]

原生Django实现增删改查逻辑

模型models.py

from django.db import models

# Create your models here.

#定义图书模型类BookInfo
class BookInfo(models.Model):
    btitle = models.CharField(max_length=20, verbose_name='名称')
    bpub_date = models.DateField(verbose_name='发布日期')
    bread = models.IntegerField(default=0, verbose_name='阅读量')
    bcomment = models.IntegerField(default=0, verbose_name='评论量')
    is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')

    class Meta:
        db_table = 'tb_books'  # 指明数据库表名
        verbose_name = '图书'  # 在admin站点中显示的名称
        verbose_name_plural = verbose_name  # 显示的复数名称

    def __str__(self):
        """定义每个数据对象的显示信息"""
        return self.btitle

视图views.py:

from django.views import View
from django.http import JsonResponse
import json

from books.models import BookInfo
# Create your views here.


class BooksView(View):
    """
    获取所有和保存
    """

    def get(self, request):
        # 1. 查询所有图书对象
        books = BookInfo.objects.all()
        # 2. 返回图书数据 [{},{}]
        book_list = []
        for book in books:
            book_list.append(
                {
                 'id': book.id,
                 'btitle': book.btitle,
                 'bread': book.bread,
                 'bcomment': book.bcomment,
                 'bpub_date': book.bpub_date,
                }
            )
        return JsonResponse(book_list, safe=False)

    def post(self, request):
        # 1. 获取前端数据
        data = request.body.decode()
        data_dict = json.loads(data)
        # 2. 验证数据
        btitle = data_dict.get('btitle')
        bpub_date = data_dict.get('bpub_date')

        if btitle is None or bpub_date is None:
            return JsonResponse({'error': '错误信息'}, status=400)
        # 3. 保存数据
        book = BookInfo.objects.create(btitle=btitle, bpub_date=bpub_date)

        # 4. 返回结果
        return JsonResponse(
            {
                'id': book.id,
                'btitle': book.btitle,
                'bread': book.bread,
                'bcomment': book.bcomment,
                'bpub_date': book.bpub_date,
            }
        )

class BookView(View):
    """
    获取单一图书和更新和删除
    """

    def get(self, request, pk):
        # 1. 查询数据对象
        try:
            book = BookInfo.objects.get(id=pk)
        except:
            return JsonResponse({'error': '错误信息'}, status=400)
        return JsonResponse(
            {
                'id': book.id,
                'btitle': book.btitle,
                'bread': book.bread,
                'bcomment': book.bcomment,
                'bpub_date': book.bpub_date,
            }
        )

    def put(self, request, pk):
        # 1. 获取前端数据
        data = request.body.decode()
        data_dict = json.loads(data)
        # 2. 验证数据
        btitle = data_dict.get('btitle')
        bpub_date = data_dict.get('bpub_date')

        if btitle is None or bpub_date is None:
            return JsonResponse({'error': '错误信息'}, status=400)
        # 3. 更新数据
        try:
            book = BookInfo.objects.get(id=pk)
        except:
            return JsonResponse({'error': '错误信息'}, status=400)

        book.btitle = btitle
        book.bpub_date = bpub_date
        book.save()
        # 4. 返回结果
        return JsonResponse(
            {
                'id': book.id,
                'btitle': book.btitle,
                'bread': book.bread,
                'bcomment': book.bcomment,
                'bpub_date': book.bpub_date,
            }
        )

    def delete(self, request, pk):
        # 1. 获取数据对象
        try:
            book = BookInfo.objects.get(id=pk)
        except:
            return JsonResponse({'error': '错误信息'}, status=400)

        book.is_delete = True
        book.save()
        # 2. 返回结果
        return JsonResponse({})

下面介绍使用Django REST framework框架后视图的变化

首先,我们需要定义一个序列化器:

序列化器的作用是:1. 进行数据的校验; 2. 对数据对象进行转换

 

常用字段类型

字段字段构造方式
BooleanFieldBooleanField()
NullBooleanFieldNullBooleanField()
CharFieldCharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)
EmailFieldEmailField(max_length=None, min_length=None, allow_blank=False)
RegexFieldRegexField(regex, max_length=None, min_length=None, allow_blank=False)
SlugFieldSlugField(maxlength=50, min_length=None, allow_blank=False)
正则字段,验证正则模式 [a-zA-Z0-9
-]+
URLFieldURLField(max_length=200, min_length=None, allow_blank=False)
UUIDFieldUUIDField(format='hex_verbose')
format:
1) 'hex_verbose' 如"5ce0e9a5-5ffa-654b-cee0-1238041fb31a"
2) 'hex' 如 "5ce0e9a55ffa654bcee01238041fb31a"
3)'int' - 如: "123456789012312313134124512351145145114"
4)'urn' 如: "urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a"
IPAddressFieldIPAddressField(protocol='both', unpack_ipv4=False, **options)
IntegerFieldIntegerField(max_value=None, min_value=None)
FloatFieldFloatField(max_value=None, min_value=None)
DecimalFieldDecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None)
max_digits: 最多位数
decimal_palces: 小数点位置
DateTimeFieldDateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)
DateFieldDateField(format=api_settings.DATE_FORMAT, input_formats=None)
TimeFieldTimeField(format=api_settings.TIME_FORMAT, input_formats=None)
DurationFieldDurationField()
ChoiceFieldChoiceField(choices)
choices与Django的用法相同
MultipleChoiceFieldMultipleChoiceField(choices)
FileFieldFileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
ImageFieldImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
ListFieldListField(child=, min_length=None, max_length=None)
DictFieldDictField(child=)

选项参数:

参数名称作用
max_length最大长度
min_lenght最小长度
allow_blank是否允许为空
trim_whitespace是否截断空白字符
max_value最小值
min_value最大值

通用参数:

参数名称说明
read_only表明该字段仅用于序列化输出,默认False
write_only表明该字段仅用于反序列化输入,默认False
required表明该字段在反序列化时必须输入,默认True
default反序列化时使用的默认值
allow_null表明该字段是否允许传入None,默认False
validators该字段使用的验证器
error_messages包含错误编号与错误信息的字典
label用于HTML展示API页面时,显示的字段名称
help_text用于HTML展示API页面时,显示的字段帮助提示信息

序列化器serializer.py

from rest_framework import serializers

from books.models import BookInfo


# 自定义序列化器
class BookSerializer(serializers.Serializer):
    # 序列化返回字段
    # write_only=True --> 该字段只参与反序列化验证过程,不参与序列化返回过程
    btitle = serializers.CharField(max_length=20, min_length=5, write_only=True)
    bread = serializers.IntegerField(max_value=100, min_value=5)
    bpub_date = serializers.DateField()
    bcomment = serializers.IntegerField(default=10)

    # 单一字段验证
    def validate_btitle(self, value):

        if value == 'ITCAST':
            raise serializers.ValidationError('书名不能是ITCAST')

        return value

    # 多个字段验证
    def validate(self, attrs):

        if attrs['bread'] > attrs['bcomment']:
            raise serializers.ValidationError('阅读量大于评论量')

        return attrs

    def create(self, validated_data):
        # {'name': 'python'}
        # 拆包: name = 'python'
        # 保存数据
        book = BookInfo.objects.create(**validated_data)

        return book

    def update(self, instance, validated_data):
        # 更新数据
        instance.btitle = validated_data['btitle']
        instance.bread = validated_data['bread']
        instance.save()
        return instance

当引入序列化器后,我们视图变化如下:

    def post(self, request):
        # 1. 获取前端数据
        data = request.body.decode()
        data_dict = json.loads(data)
        # 2. 验证数据
        btitle = data_dict.get('btitle')
        bpub_date = data_dict.get('bpub_date')

        if btitle is None or bpub_date is None:
            return JsonResponse({'error': '错误信息'}, status=400)
        # 3. 保存数据
        book = BookInfo.objects.create(btitle=btitle, bpub_date=bpub_date)

        # 4. 返回结果
        return JsonResponse(
            {
                'id': book.id,
                'btitle': book.btitle,
                'bread': book.bread,
                'bcomment': book.bcomment,
                'bpub_date': book.bpub_date,
            }
        )

-------------------------->

    def post(self, request):
        # 1. 获取前端数据
        data = request.body.decode()
        data_dict = json.loads(data)
        # 2. 验证数据
        ser = BookSerializer(data=data_dict)
        # 验证方法 raise_exception=True--->检测到错误自动抛出异常并返回
        # ser.is_valid(raise_exception=True)
        ser.is_valid()
        # 获取验证后的字段数据
        # print(ser.validated_data)
        # 3. 保存数据
        ser.save()

        # 4. 返回结果
        return JsonResponse(ser.data)

接着,我们的视图也会发生相应变化,视图的变化相对复杂。

类视图  - 两个基本类视图(继承自Django的View类的APIView + 继承自APIView的GenericAPIview)+ 五个拓展类(需要配合GenericAPIview使用,继承自Object,分别为:ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin ,DestroyModelMixin )+ 拓展类子类(ListCreateAPIView, ListAPIView, CreateAPIView, DestroyAPIView, RetrieveDestroyAPIView, RetrieveAPIView, RetrieveUpdateAPIView, RetrieveUpdateDestroyAPIView, UpdateAPIView)。

视图集 - 两个基本视图集(继承自APIView的ViewSet,继承自GenericAPIview的GenericViewset ) + 两个拓展视图集(ModelViewSet和ReadOnlyModelViewSet)

类视图 - 两个基本类视图

APIView :主要在于Request和Response的区别

原生Django获取前端数据的方法:

        data = request.body.decode()
        data_dict = json.loads(data)

使用APIView后获取前端数据的方法:

data = request.data

另外响应Response也会不同,原生Django响应数据使用JsonResponse,并且需要手动拼接Json数据

        return JsonResponse(
            {
                'id': book.id,
                'btitle': book.btitle,
                'bread': book.bread,
                'bcomment': book.bcomment,
                'bpub_date': book.bpub_date,
            }
        )

使用APIView后响应Response的方法:

return Response(ser.data)

完整视图函数views.py

from rest_framework.views import APIView
from rest_framework.response import Response

from book_drf.serializer import BookSerializer
from books.models import BookInfo
# Create your views here.


class Books(APIView):

    def get(self, request):
        # print(request.query_params)
        # 1. 查询所有图书对象
        books = BookInfo.objects.all()
        # many=True ---> 返回多个数据
        ser = BookSerializer(books, many=True)
        return Response(ser.data)

    def post(self, request):
        # 1. 获取前端数据
        data = request.data
        # 2. 验证数据
        ser = BookSerializer(data=data)
        # 验证方法 raise_exception=True--->检测到错误自动抛出异常并返回
        # ser.is_valid(raise_exception=True)
        ser.is_valid()
        # 3. 保存数据
        ser.save()
        # 4. 返回结果
        return Response(ser.data)


class BookDRFView(APIView):
    """
    获取当一和更新和删除
    """
    def get(self, request, pk):
        # 1. 查询数据对象
        try:
            book = BookInfo.objects.get(id=pk)
        except:
            return Response({'error': '错误信息'}, status=400)

        ser = BookSerializer(book)
        return Response(ser.data)

    def put(self, request, pk):
        # 1. 获取前端数据
        data = request.data
        # 2. 验证数据
        try:
            book = BookInfo.objects.get(id=pk)
        except:
            return Response({'error': '错误信息'}, status=400)

        ser = BookSerializer(book, data=data)
        ser.is_valid()
        # 3. 更新数据
        ser.save()
        # 4. 返回结果
        return Response(ser.data)

    def delete(self, request, pk):
        # 1. 获取数据对象
        try:
            book = BookInfo.objects.get(id=pk)
        except:
            return Response({'error': '错误信息'}, status=400)

        book.is_delete = True
        book.save()
        # 2. 返回结果
        return Response({})

GenericAPIview:

  • queryset 列表视图的查询集
  • serializer_class 视图使用的序列化器

主要区别在于定义类视图时需要声明当前类视图使用的查询集数据,以及当前类视图使用的序列化器

    queryset = BookInfo.objects.all()   # 指定当前类视图使用的查询集数据
    serializer_class = BookSerializer   # 指定当前类视图使用的序列化器

另外,在获取查询集中所有数据时使用:

books = self.get_queryset()     # 获取查询集中的所有数据

在获取单一数据时使用:

book = self.get_object() 

完整的视图views.py:

from rest_framework.generics import GenericAPIView
from rest_framework.response import Response

from book_drf.serializer import BookSerializer
from books.models import BookInfo
# Create your views here.


class Books(GenericAPIView):

    queryset = BookInfo.objects.all()   # 指定当前类视图使用的查询集数据
    serializer_class = BookSerializer   # 指定当前类视图使用的序列化器

    def get(self, request):
        # 1. 查询所有图书对象
        books = self.get_queryset()     # 获取查询集中的所有数据
        # many=True ---> 返回多个数据
        ser = self.get_serializer(books, many=True)     # 使用序列化器,获取序列化器对象
        return Response(ser.data)

    def post(self, request):
        # 1. 获取前端数据
        data = request.data
        # 2. 验证数据
        ser = self.get_serializer(data=data)
        # 验证方法 raise_exception=True--->检测到错误自动抛出异常并返回
        # ser.is_valid(raise_exception=True)
        ser.is_valid()
        # 获取验证后的字段数据
        # print(ser.validated_data)
        # 3. 保存数据
        ser.save()

        # 4. 返回结果
        # return JsonResponse(ser.data)
        return Response(ser.data)


class BookDRFView(GenericAPIView):
    """
    获取当一和更新和删除
    """
    queryset = BookInfo.objects.all()   # 指定当前类视图使用的查询集数据
    serializer_class = BookSerializer   # 指定当前类视图使用的序列化器

    def get(self, request, pk):
        # 1. 查询数据对象
        try:
            book = self.get_object()    # 根据pk值,从查询集中获取指定的单数据对象
        except:
            return Response({'error': '错误信息'}, status=400)

        ser = BookSerializer(book)
        return Response(ser.data)

    def put(self, request, pk):
        # 1. 获取前端数据
        # data = request.body.decode()
        # data_dict = json.loads(data)
        data = request.data
        # 2. 验证数据
        try:
            book = self.get_object()        # 从查询集中获取指定的单数据对象
        except:
            return Response({'error': '错误信息'}, status=400)

        ser = BookSerializer(book, data=data)
        ser.is_valid()
        # 3. 更新数据
        ser.save()
        # 4. 返回结果
        return Response(ser.data)

    def delete(self, request, pk):
        # 1. 获取数据对象
        try:
            book = self.get_object()
        except:
            return Response({'error': '错误信息'}, status=400)

        book.is_delete = True
        book.save()
        # 2. 返回结果
        return Response({})

类视图 - 五个拓展类

ListModelMixin 列表视图扩展类,提供list(request, *args, **kwargs)方法快速实现列表视图,返回200状态码。

CreateModelMixin 创建视图扩展类,提供create(request, *args, **kwargs)方法快速实现创建资源的视图,成功返回201状态码。

RetrieveModelMixin 详情视图扩展类,提供retrieve(request, *args, **kwargs)方法,可以快速实现返回一个存在的数据对象。如果存在,返回200, 否则返回404。

UpdateModelMixin 更新视图扩展类,提供update(request, *args, **kwargs)方法,可以快速实现更新一个存在的数据对象。成功返回200,序列化器校验数据失败时,返回400错误。

DestroyModelMixin 删除视图扩展类,提供destroy(request, *args, **kwargs)方法,可以快速实现删除一个存在的数据对象。成功返回204,不存在返回404。

在实现增删改查的业务逻辑时,定义视图类时,继承的子类由业务逻辑需要来定。比如:

class Books(GenericAPIView, CreateModelMixin, ListModelMixin):
    """获取所有数据对象和增加"""
    pass


class BookDRFView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    """获取单一数据对象、更新和删除"""
    pass

视图完整代码views.py

from rest_framework.generics import GenericAPIView
from rest_framework.mixins import CreateModelMixin, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, ListModelMixin

from book_drf.serializer import BookSerializer
from books.models import BookInfo
# Create your views here.


class Books(GenericAPIView, CreateModelMixin, ListModelMixin):

    queryset = BookInfo.objects.all()   # 指定当前类视图使用的查询集数据
    serializer_class = BookSerializer   # 指定当前类视图使用的序列化器

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

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


class BookDRFView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    """
    获取当一和更新和删除
    """
    queryset = BookInfo.objects.all()   # 指定当前类视图使用的查询集数据
    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)

源码分析:以CreateModelMixin为例

class CreateModelMixin:
    """
    Create a model instance.
    """
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    def perform_create(self, serializer):
        serializer.save()

    def get_success_headers(self, data):
        try:
            return {'Location': str(data[api_settings.URL_FIELD_NAME])}
        except (TypeError, KeyError):
            return {}

可以看出CreateModelMixin类实际上封装了:

        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)

类视图 - 九个拓展类子类

完整视图views.py

from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView

from book_drf.serializer import BookSerializer
from books.models import BookInfo
# Create your views here.


class Books(ListCreateAPIView):
    """获取所有和添加"""

    queryset = BookInfo.objects.all()   # 指定当前类视图使用的查询集数据
    serializer_class = BookSerializer   # 指定当前类视图使用的序列化器


class BookDRFView(RetrieveUpdateDestroyAPIView):
    """
    获取当一和更新和删除
    """
    queryset = BookInfo.objects.all()   # 指定当前类视图使用的查询集数据
    serializer_class = BookSerializer   # 指定当前类视图使用的序列化器

 

视图集 - 两个基本视图集

ViewSet:继承自APIView,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。

使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中:

  • list() 提供一组数据
  • retrieve() 提供单个数据
  • create() 创建数据
  • update() 保存数据
  • destory() 删除数据

ViewSet视图集类不再实现get()、post()等方法,而是实现动作 action 如 list() 、create() 等。

视图集只在使用as_view()方法的时候,才会将action动作与具体请求方式对应上。如:

from rest_framework.viewsets import ViewSet
from rest_framework.response import Response

from book_drf.serializer import BookSerializer
from books.models import BookInfo
# Create your views here.


class Books(ViewSet):

    def list(self, request):
        # 1. 查询所有图书对象
        books = BookInfo.objects.all()
        # many=True ---> 返回多个数据
        ser = BookSerializer(books, many=True)
        return Response(ser.data)

    def create(self, request):
        # 1. 获取前端数据
        data = request.data
        # 2. 验证数据
        ser = BookSerializer(data=data)
        # 验证方法 raise_exception=True--->检测到错误自动抛出异常并返回
        # ser.is_valid(raise_exception=True)
        ser.is_valid()
        # 获取验证后的字段数据
        # print(ser.validated_data)
        # 3. 保存数据
        ser.save()
        # 4. 返回结果
        return Response(ser.data)


class BookDRFView(ViewSet):
    """
    获取当一和更新和删除
    """
    def retrieve(self, request, pk):
        """获取单一数据"""
        try:
            book = BookInfo.objects.get(id=pk)
        except:
            return Response({'error': '错误信息'}, status=400)

        ser = BookSerializer(book)
        return Response(ser.data)

    def update(self, request, pk):
        """更新数据"""
        # 1. 获取前端数据
        data = request.data
        # 2. 验证数据
        try:
            book = BookInfo.objects.get(id=pk)
        except:
            return Response({'error': '错误信息'}, status=400)

        ser = BookSerializer(book, data=data)
        ser.is_valid()
        # 3. 更新数据
        ser.save()
        # 4. 返回结果
        return Response(ser.data)

    def destroy(self, request, pk):
        """删除单一数据"""
        try:
            book = BookInfo.objects.get(id=pk)
        except:
            return Response({'error': '错误信息'}, status=400)

        book.is_delete = True
        book.save()
        # 2. 返回结果
        return Response({})

路由配置urls.py

urlpatterns = [
    url(r'^books_drf/$', viewset_view.Books.as_view({'get': 'list', 'post': 'create'})),
    url(r'^books_drf/(?P<pk>\d+)/$', viewset_view.BookDRFView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
]

 

GenericViewSet: 继承自GenericAPIView,作用也与GenericAPIVIew类似,提供了get_object、get_queryset等方法便于列表视图与详情信息视图的开发。

完整视图views.py

from rest_framework.viewsets import GenericViewSet
from rest_framework.response import Response

from book_drf.serializer import BookSerializer
from books.models import BookInfo
# Create your views here.


class Books(GenericViewSet):
    queryset = BookInfo.objects.all()       # 指定当前类视图使用的查询集数据
    serializer_class = BookSerializer       # 指定当前类视图使用的序列化器

    def list(self, request):
        # 1. 查询所有图书对象
        books = self.get_queryset()
        ser = self.get_serializer(books, many=True)
        return Response(ser.data)

    def create(self, request):
        # 1. 获取前端数据
        data = request.data
        # 2. 验证数据
        ser = self.get_serializer(data=data)
        # 验证方法 raise_exception=True--->检测到错误自动抛出异常并返回
        # ser.is_valid(raise_exception=True)
        ser.is_valid()
        # 3. 保存数据
        ser.save()
        # 4. 返回结果
        return Response(ser.data)


class BookDRFView(GenericViewSet):
    """
    获取当一和更新和删除
    """
    def retrieve(self, request, pk):
        """获取当一数据"""
        try:
            book = BookInfo.objects.get(id=pk)
        except:
            return Response({'error': '错误信息'}, status=400)
        ser = BookSerializer(book)
        return Response(ser.data)

    def update(self, request, pk):
        """更新数据"""
        # 1. 获取前端数据
        data = request.data
        # 2. 验证数据
        try:
            book = BookInfo.objects.get(id=pk)
        except:
            return Response({'error': '错误信息'}, status=400)
        ser = BookSerializer(book, data=data)
        ser.is_valid()
        # 3. 更新数据
        ser.save()
        # 4. 返回结果
        return Response(ser.data)

    def destroy(self, request, pk):
        """删除单一数据"""
        try:
            book = BookInfo.objects.get(id=pk)
        except:
            return Response({'error': '错误信息'}, status=400)
        book.is_delete = True
        book.save()
        # 返回结果
        return Response({})

路由配置urls.py

urlpatterns = [
    url(r'^books_drf/$', genericviewset_view.Books.as_view({'get': 'list', 'post': 'create'})),
    url(r'^books_drf/(?P<pk>\d+)/$', genericviewset_view.BookDRFView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
]

视图集 - 拓展类视图ModelViewSet

继承自GenericAPIVIew,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。

from rest_framework.viewsets import ModelViewSet

from books.models import BookInfo
from book_drf.serializer import BookSerializer


class Books(ModelViewSet):
    queryset = BookInfo.objects.all()       # 指定当前类视图使用的查询集数据
    serializer_class = BookSerializer       # 指定当前类视图使用的序列化器

路由匹配urls.py

urlpatterns = [
    url(r'^books_drf/$', modelview_set.Books.as_view({'get': 'list', 'post': 'create'})),
    url(r'^books_drf/(?P<pk>\d+)/$', modelview_set.Books.as_view({'put': 'update', 'get': 'retrieve', 'delete': 'destroy'})),
]

源码分析:

class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):
    """
    A viewset that provides default `create()`, `retrieve()`, `update()`,
    `partial_update()`, `destroy()` and `list()` actions.
    """
    pass

由于ModelViewSet继承自mixins.CreateModelMixin,mixins.RetrieveModelMixin,mixins.UpdateModelMixin, mixins.DestroyModelMixin,mixins.ListModelMixin,GenericViewSet。因此会根据请求方法,根据不同场景适配不同处理方法。

 

补充:视图集中定义附加action动作

在视图集中,除了上述默认的方法动作外,还可以添加自定义动作。

添加自定义动作需要使用rest_framework.decorators.action装饰器。

以action装饰器装饰的方法名会作为action动作名,与list、retrieve等同。

action装饰器可以接收两个参数:

  • methods: 该action支持的请求方式,列表传递
  • detail: 表示是action中要处理的是否是视图资源的对象(即是否通过url路径获取主键)
    • True 表示使用通过URL获取的主键对应的数据对象
    • False 表示不使用URL获取主键

完整视图views.py

from rest_framework.viewsets import ModelViewSet
from rest_framework.response import Response
from rest_framework.decorators import action

from books.models import BookInfo
from book_drf.serializer import BookSerializer


class Books(ModelViewSet):
    queryset = BookInfo.objects.all()       # 指定当前类视图使用的查询集数据
    serializer_class = BookSerializer       # 指定当前类视图使用的序列化器


    # detail为False 表示不需要处理具体的BookInfo对象
    @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主键对应的BookInfo对象
    @action(methods=['put'], detail=True)
    def read(self, request, pk):
        """
        修改图书的阅读量数据
        """
        book = self.get_object()
        book.bread = request.data.get('bread')
        book.save()
        serializer = self.get_serializer(book)
        return Response(serializer.data)

  匹配路由urls.py

 

urlpatterns = [
    url(r'^books_drf/latest/$', modelview_set.Books.as_view({'get': 'latest'})),
    url(r'^books_drf/(?P<pk>\d+)/read/$', modelview_set.Books.as_view({'put': 'read'})),
]

       
                   
                 
                   
                   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WUYANGEZRA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值