Django--004 DRF

1. 简介

  • 定义
  • 在Django框架基础上进行二次开发,用于构建Restful API,简称DRF
  • 特性
  • 强大的Serializer序列化器,可以高效的进行序列化和反序列化操作;
  • 极为丰富的类视图、Mixin扩展类、ViewSet视图集;
  • 提供直观的WEB API界面;
  • 多种身份认证和权限认证;
  • 强大的排序、过滤、分页、搜索、限流等功能;
  • 可扩展性,插件丰富

2. 安装配置

  • 安装
pip install djangorestframework
  • 配置
# 可理解为子应用,在settings.py文件中设置即可
INSTALLED_APPS = [
    'rest_framework'
]

3. 序列化器(serializer)

3.1 序列化器

  • 序列化:将Django模型数据转化为json格式字符串(前段可接收的数据),为序列化
  • 反序列化:前段传过来的json格式数据,转化为Django模型类对象,为反序列化
  • 序列化器:具有序列化和反序列化的功能

3.2 代码

  • model.py
from django.db import models


class Projects(models.Model):
    # verbose_name -字段名,   help_text - api文档的中文名
    pj_name = models.CharField(verbose_name='项目名称', max_length=64, help_text='项目名称', unique=True)
    pj_leader = models.CharField(verbose_name='项目负责人', max_length=32, help_text='项目负责人')
    pj_developer = models.CharField(verbose_name='开发人员', max_length=32, help_text='开发人员')
    pj_tester = models.CharField(verbose_name='测试人员', max_length=32, help_text='测试人员')
    pj_app_name = models.CharField(verbose_name='应用名称', max_length=32, help_text='应用名称')
    pj_app_version = models.CharField(verbose_name='应用版本', max_length=32, help_text='应用版本')
    # null -字段允许为空, blank - 前端可不传参数, default - 默认值
    pj_desc = models.TextField(verbose_name='项目概述', max_length=256, help_text='项目概述', blank=True, default='', null=True)

    class Meta:
        """
        表名
        """
        db_table = 'tb_projects'
        verbose_name = '项目'
        verbose_name_plural = '项目'

    def __str__(self):
        """
        修改admin后台展示的项目名称
        """
        return self.pj_name
  • serializer.py
from rest_framework import serializers
from rest_framework.validators import UniqueValidator
from projects.models import Projects


# 自定义外部校验器
def is_unique_project_name(name):
    if '项目' not in name:
        raise serializers.ValidationError('项目名称中必须包含"项目"')


# 序列化器
class ProjectSerializer(serializers.Serializer):
    """
    label <===> verbose_name
    read_only=True: 表该字段只能进行序列化输出
    write_only=True:表该字段只能进行反序列化输入
    """
    id = serializers.IntegerField(label='ID', read_only=True)
    pj_name = serializers.CharField(label='项目名称', max_length=64, min_length=4, help_text='项目名称',
                                    validators=[UniqueValidator(queryset=Projects.objects.all(), message='项目名称不能重复'),
                                                is_unique_project_name],
                                    error_messages={
    
    'max_length': '项目名称不能超过64个字节', 'min_length': '项目名称不能少于4个字节'})
    pj_leader = serializers.CharField(label='项目负责人', max_length=32, help_text='项目负责人', write_only=True)
    pj_developer = serializers.CharField(label='开发人员', max_length=32, help_text='开发人员')
    pj_tester = serializers.CharField(label='测试人员', max_length=32, help_text='测试人员')
    pj_app_name = serializers.CharField(label='应用名称', max_length=32, help_text='应用名称')
    pj_app_version = serializers.CharField(label='应用版本', max_length=32, help_text='应用版本')
    pj_desc = serializers.CharField(label='项目概述', max_length=256, help_text='项目概述', allow_null=True, allow_blank=True,
                                    default='')

    # 自定义内部校验器,不需要在validators校验列表中添加
    # 执行顺序:先执行validators列表中校验器,且列表中校验器都会执行,均校验通过后再执行内部字段校验器
    # ----单字段校验器
    def validate_pj_name(self, value):
        if not value.endswith('项目'):
            raise serializers.ValidationError('项目名称必须以"项目"结尾')
        return value

    # ----多字段校验器
    def validate(self, attrs):
        """
        多字段校验器
        """
        if '张三' not in attrs['pj_developer'] and '张三' not in attrs['pj_tester']:
            raise serializers.ValidationError('"张三"必须是项目开发人员或测试人员')
        return attrs

    def create(self, validated_data):
        return Projects.objects.create(**validated_data)

    def update(self, instance, validated_data):
        instance.pj_name = validated_data['pj_name']
        instance.pj_leader = validated_data['pj_leader']
        instance.pj_developer = validated_data['pj_developer']
        instance.pj_tester = validated_data['pj_tester']
        instance.pj_app_name = validated_data['pj_app_name']
        instance.pj_app_version = validated_data['pj_app_version']
        instance.pj_desc = validated_data['pj_desc']
        instance.save()
        return instance
  • view.py
from django.http import HttpResponse, JsonResponse, Http404
from django.views import View
from projects.models import Projects
from projects.serializer import ProjectSerializer
import json


class ProjectList(View):
    """"
    类视图
    """

    def get(self, request):
        projects= Projects.objects.all()
        # many=True: 输出querySet,返回多条数据
        serializer = ProjectSerializer(instance=projects, many=True)
        return JsonResponse(serializer.data, safe=False, status=200)

    def post(self, request):
        """
        httpie模拟请求:http POST :8000/projects/ pj_name='项目009' pj_leader="zz" pj_developer='李四' \
                    pj_tester='王五' pj_app_name='测试应用' pj_app_version='1.0' pj_desc='demo desc'
        """
        # 1. 前端传入json数据转为python_data
        data = json.loads(request.body.decode('utf-8'), encoding='utf-8')
        # 2. 数据校验
        serializer = ProjectSerializer(data=data)
        try:
            # 设置raise_exception=True后serializer.errors可以获取到报错信息
            serializer.is_valid(raise_exception=True)
        except Exception as e:
            # 3. 校验失败则返回异常dict
            return JsonResponse(serializer.errors)
        # 3. 校验通过则调用序列化器的save方法(会调用序列化器的create方法)新建数据
        serializer.save()   
        # 返回新建成功的这条数据
        return JsonResponse(serializer.data, safe=False, status=201)


class ProjectDetail(View):
    def get_object(self, pk):
        """
        根据id判断项目是否存在,存在则返回,不存在则返回404
        """
        try:
            return Projects.objects.get(id=pk)
        except Projects.DoesNotExist:
            raise Http404

    def get(self, request, pk):
        """
        httpie模拟请求:http  :8000/projects/12
        """
        project= self.get_object(pk)
        serializer = ProjectSerializer(instance=project)
        return JsonResponse(serializer.data, safe=False)

    def put(self, request, pk):
        """
        httpie模拟请求:http PUT :8000/projects/12 pj_name='项目0091' pj_leader="张三" pj_developer='李四' \
                                pj_tester='王五' pj_app_name='测试应用' pj_app_version='1.0' pj_desc='demo desc'
        """
        # 1.判断数据是否存在
        project = self.get_object(pk)
        # 2. 将前端数据反序列化为模型可解析的数据
        data = json.loads(request.body.decode('utf-8'), encoding='utf-8')
        # 同时存在反序列化和序列化时,同时传参会调用序列化器update方法
        serializer = ProjectSerializer(instance=project, data=data)
        try:
            serializer.is_valid(raise_exception=True)
        except Exception as e:
            # 3. 校验失败则返回异常dict
            return JsonResponse(serializer.errors)
        # 4. 校验通过则更新
        # ----调用save方法会调用序列化器的update方法
        serializer.save()  
        return JsonResponse(serializer.data, safe=False, status=201)

    def delete(self, request, pk):
        """
        httpie模拟请求:http DELETE :8000/projects/12
        """
        # 1. 判断数据是否存在
        project = self.get_object(pk)
        # 2. 删除
        project.delete()
        return JsonResponse(None, safe=False, status=204)

4. 模型序列化器(ModelSerializer)

4.1 模型序列化器

  • 功能与特点:
  • 功能同序列化器,但简化了序列化器的定义
  • 基于模型类生成一系列字段
  • 基于模型类自动为serializer生成validators,比如unique_together
  • 包含默认的create()和update()功能的实现
  • 关联字段序列化
  • PrimaryKeyRelatedField
  • StringRelatedField
  • SlugRelatedField

4.2 代码

  • 数据库模型
# projects/model.py

from django.db import models


class Projects(models.Model):
    # verbose_name -字段名,   help_text - api文档的中文名
    pj_name = models.CharField(verbose_name='项目名称', max_length=64, help_text='项目名称', unique=True)
    pj_leader = models.CharField(verbose_name='项目负责人', max_length=32, help_text='项目负责人')
    pj_developer = models.CharField(verbose_name='开发人员', max_length=32, help_text='开发人员')
    pj_tester = models.CharField(verbose_name='测试人员', max_length=32, help_text='测试人员')
    pj_app_name = models.CharField(verbose_name='应用名称', max_length=32, help_text='应用名称')
    pj_app_version = models.CharField(verbose_name='应用版本', max_length=32, help_text='应用版本')
    # null -字段允许为空, blank - 前端可不传参数, default - 默认值
    pj_desc = models.TextField(verbose_name='项目概述', max_length=256, help_text='项目概述', blank=True, default='', null=True)

    class Meta:
        """
        表名
        """
        db_table = 'tb_projects'
        verbose_name = '项目'
        verbose_name_plural = '项目'

    def __str__(self):
        """
        修改admin后台展示的项目名称
        """
        return self.pj_name
# interfaces/model.py 
from django.db import models


class Interfaces(models.Model):
    # verbose_name -字段名,   help_text - api文档的中文名
    name = models.CharField(verbose_name='接口名称', max_length=64, unique=True, help_text='接口名称')
    tester = models.CharField(verbose_name='测试人员', max_length=32, help_text='测试人员')
    desc = models.TextField(verbose_name='接口描述', max_length=256, help_text='接口概述', blank=True, default='', null=True)
    # 外键
    # CASCADE--父表删除后,子表也会被删除,null=True
    # SET_NULL--父表删除后,当前外键会被设置为None
    # SET_DEFAULT--父表删除后,子表需要设置默认值,null=True
    project = models.ForeignKey('projects.Projects', on_delete=models.CASCADE, verbose_name='所属项目', help_text='所属项目')

    class Meta:
        db_table = 'tb_interfaces'
        verbose_name = '接口'
        verbose_name_plural = '接口'

    def __str__(self):
        return self.name
  • 模型序列化器
# projects/serializer.py

from rest_framework import serializers
from rest_framework.validators import UniqueValidator
from projects.models import Projects


# 自定义外部校验器
def is_unique_project_name(name):
    if '项目' not in name:
        raise serializers.ValidationError('项目名称中必须包含"项目"')


class ProjectModelSerializer(serializers.ModelSerializer):
    """"""
    # 如果有自定义字段,则以自定义字段为准
    pj_name = serializers.CharField(label='项目名称', max_length=64, help_text='项目名称',
                                    validators=[
                                        UniqueValidator(queryset=Projects.objects.all(), message='项目名称不能重复'),
                                        is_unique_project_name])

    # 可以额外定义数据库没有的字段

    # 父表默认不会生成子表字段序列化器具,需要指定
    interfaces_set = serializers.StringRelatedField(many=True)

    class Meta:
        # 指定参考哪个模型来创建
        model = Projects
        # 自定义序列化器字段
        # ---全部字段
        # fields = "__all__"
        # ---指定字段生成
        # fields = ('id', 'pj_name', 'pj_leader')
        # ---指定哪些字段不生成
        exclude = ('pj_desc', 'pj_app_version')
        # ---设置read_only=True属性
        read_only_fields = ('id', 'pj_desc')

        # 定义序列化器各字段约束及提示等信息
        extra_kwargs = {
    
    
            'pj_name': {
    
    
                'label': '项目名称',
                'max_length': 64,
                'min_length': 4,
                'write_only': False,
                'error_message': {
    
    'max_length': '最大长度不超过50字节'},
                'validators': [UniqueValidator(queryset=Projects.objects.all(), message='项目名称不能重复'),
                                                is_unique_project_name]
            },
            'pj_leader': {
    
    
                'label': '项目负责人',
            }
        }

    # 自定义内部校验器,不需要在validators校验列表中添加
    # 执行顺序:先执行validators列表中校验器, 后执行内部字段校验器
    # ----单字段校验器
    def validate_pj_name(self, value):
        if not value.endswith('项目'):
            raise serializers.ValidationError('项目名称必须以"项目"结尾')
        return value

    # ----多字段校验器
    def validate(self, attrs):
        if '张三' not in attrs['pj_developer'] and '张三' not in attrs['pj_tester']:
            raise serializers.ValidationError('"张三"必须是项目开发人员或测试人员')
        return attrs
# interfaces/serializer.py

from rest_framework import serializers
from interfaces.models import Interfaces
from projects.serializer import ProjectModelSerializer


class InterfaceModelSerializer(serializers.ModelSerializer):
    """
    """
    # 1. 数据库模型中的外键字段,默认会生成PrimaryKeyRelatedField序列化器字段,默认输出外键ID值
    # 2. StringRelatedField 字段将被序列化为关联字符串表达形式(即__str__方法返回值),即ID对应的项目名称
    # project = serializers.StringRelatedField(help_text='项目名称')
    # 3. SlugRelatedField, 此字段将被序列化为关联对象的制定字段
    # project = serializers.SlugRelatedField(slug_field='pj_leader')
    # 4. 使用关联字段的序列化器,输出关联字段序列化对象
    project = ProjectModelSerializer(label='所属项目', read_only=True)

    class Meta:
        # 指定参考哪个模型来创建
        model = Interfaces
        fields = "__all__"
  • 视图
# projects/view.py

# -*-coding:utf-8 -*-

from django.http import HttpResponse, JsonResponse, Http404
from django.views import View
from projects.models import Projects
from projects.serializer import ProjectModelSerializer
import json


class ProjectList(View):
    """"
    类视图
    """
    def get(self, request):
        projects = Projects.objects.all()
        # many=True: 输出querySet,返回多条数据
        # serializer = ProjectSerializer(instance=projects, many=True)
        serializer = ProjectModelSerializer(instance=projects, many=True)

        return JsonResponse(serializer.data, safe=False, status=200)

    def post(self, request):
        """
        httpie模拟请求:http POST :8000/projects/ pj_name='项目009' pj_leader="zz" pj_developer='李四' pj_tester='王五' pj_app_name='测试应用' pj_app_version='1.0' pj_desc='demo desc'
        """
        # 1. 前端传入json数据反序列化为模型数据
        data = json.loads(request.body.decode('utf-8'), encoding='utf-8')
        # 2. 数据校验
        serializer = ProjectModelSerializer(data=data)
        try:
            serializer.is_valid(raise_exception=True)
        except Exception as e:
            # 3. 校验失败则返回异常dict
            return JsonResponse(serializer.errors)
        serializer.save()   # 调用save方法会调用序列化器的create方法
        return JsonResponse(serializer.data, safe=False, status=201)


class ProjectDetail(View):
    def get_object(self, pk):
        try:
            return Projects.objects.get(id=pk)
        except Projects.DoesNotExist:
            raise Http404

    def get(self, request, pk):
        """
        httpie模拟请求:http  :8000/projects/12
        """
        project= self.get_object(pk)
        serializer = ProjectModelSerializer(instance=project)
        return JsonResponse(serializer.data, safe=False)

    def put(self, request, pk):
        """
        httpie模拟请求:http PUT :8000/projects/12 pj_name='项目0091' pj_leader="张三" pj_developer='李四' pj_tester='王五' pj_app_name='测试应用' pj_app_version='1.0' pj_desc='demo desc'
        """
        # 1.判断数据是否存在
        project = self.get_object(pk)
        # 2. 将前端数据反序列化为模型数据
        data = json.loads(request.body.decode('utf-8'), encoding='utf-8')
        # 3. 数据合法性校验
        # serializer = ProjectSerializer(data=update_project_data)
        # 同时存在反序列化和序列化时,同时传参会调用序列化器update方法
        serializer = ProjectModelSerializer(instance=project, data=data)
        try:
            serializer.is_valid(raise_exception=True)
        except Exception as e:
            # 3. 校验失败则返回异常dict
            return JsonResponse(serializer.errors)
        serializer.save()  # 调用save方法会调用序列化器的update方法
        return JsonResponse(serializer.data, safe=False, status=201)

    def delete(self, request, pk):
        """
        httpie模拟请求:http DELETE :8000/projects/12
        """
        # 1. 判断数据是否存在
        project = self.get_object(pk)
        # 2. 删除
        project.delete()
        return JsonResponse(None, safe=False, status=204)
# interfaces/view.py

# -*-coding:utf-8 -*-

from django.http import HttpResponse, JsonResponse, Http404
from django.views import View
from interfaces.models import Interfaces
from interfaces.serializer import InterfaceModelSerializer
import json


class InterfaceList(View):
    """"
    类视图
    """
    def get(self, request):
        """
        httpie模拟请求:http :8000/interfaces/
        """
        interfaces = Interfaces.objects.all()
        serializer = InterfaceModelSerializer(instance=interfaces, many=True)
        return JsonResponse(serializer.data, safe=False, status=200)

    def post(self, request):
        """
        httpie模拟请求:http POST :8000/interfaces/ name='接口001' tester="吴用" desc='这是第一个测试接口' project_id=1
        """
        # 1. 前端传入json数据反序列化为模型数据
        data = json.loads(request.body.decode('utf-8'), encoding='utf-8')
        # 2. 数据校验
        serializer = InterfaceModelSerializer(data=data)
        try:
            serializer.is_valid(raise_exception=True)
        except Exception as e:
            # 3. 校验失败则返回异常dict
            return JsonResponse(serializer.errors)
        serializer.save()   # 调用save方法会调用序列化器的create方法
        return JsonResponse(serializer.data, safe=False, status=201)

5. 请求和响应

5.1 Request及APIView

  • request.data
  • :可以解析form-data和json格式的传参,此时类视图需要继承自DRF的APIView。
  • APIView
  • 继承自Django的View
  • 与View的区别
    1. 继承APiView的视图,传入到视图的是Request对象而不是Django的HttpRequest对象
    2. 视图方法可以返回Response对象,会为响应数据处理(render)为符合前段要求的格式
    3. 任何APIException异常都会被捕获到,并且处理成合适的响应信息
    4. 在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制

5.2 Response

  • Response源码参数
Response(data=None, status=None, template_name=None, headers=None, exception=False, content_type=None)
    """
    :params data: 序列化处理后的数据,一般为 serializer.data
    :params status: 状态码,默认200
    :params template_name: 模板名称,使用HTMLRenderer渲染是需要指明
    :params headers: 响应头
    :params exception: 异常
    :params content_type: 响应头中的Content_Type,无需设置,会自动根据前端前端所需类型来设置
    """
  • DRF响应配置
# settings.py

# DRF配置信息
REST_FRAMEWORK = {
    
    
    # 默认响应渲染类
    'DEFAULT_RENDERER_CLASSES': (
        # json渲染器为第一优先级
        'rest_framework.renderers.JSONRenderer',
        # 可浏览的API渲染器为第二优先级
        'rest_framework.renderers.BrowsableAPIRenderer',
    )

}

5.3 APIView和Response代码

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from projects.models import Projects
from projects.serializer import ProjectModelSerializer


class ProjectList(APIView):
    """"
    类视图
    """
    def get(self, request):
        projects = Projects.objects.all()
        serializer = ProjectModelSerializer(instance=projects, many=True)

        return Response(serializer.data, status=status.HTTP_200_OK)

    def post(self, request):
        """h
        httpie json格式请求模拟:http POST :8000/projects/ pj_name='项目009' pj_leader="zz" pj_developer='李四' pj_tester='王五' pj_app_name='测试应用' pj_app_version='1.0' pj_desc='demo desc'
        httpie form-data格式请求模拟:http -f POST :8000/projects/ pj_name='项目009' pj_leader="zz" pj_developer='李四' pj_tester='王五' pj_app_name='测试应用' pj_app_version='1.0' pj_desc='demo desc'
        """
        serializer = ProjectModelSerializer(data=request.data)
        try:
            serializer.is_valid(raise_exception=True)
        except Exception as e:
            return Response(serializer.errors)
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)

7. GenericAPIView

7.1 简介

  • 继承关系: rest_framework.generics.GenericAPIView—>rest_framework.views.APIView—>django.views.generic.base.View—>obiect—>typing.hashable
  • 必须指定的属性: queryset、serializer_class
    视图类继承自GenericAPIView后进行排序

7.2 排序

  • 配置
    方式一:类视图配置
# 1. 在类视图中指定过滤引擎,也可在全局settings.py中指定
# filter_backends = [filters.OrderingFilter]

方式二:全局设置

7.3 过滤

  • 库安装
pip install django-filter

方式一:类视图配置

# 1. 在类视图中指定过滤引擎,一般使用全局设置
filter_backends = [DjangoFilterBackend]

方式二:全局设置

7.4 分页

# 1. 在类视图中指定分页引擎,也可在全局settings.py中指定
pagination_class = PageNumberPaginationManual

方式二:全局设置

7.5 代码

  • settings.py全局配置
# settings.py

# 2. 添加'django_filters'子应用
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # 注册子应用
    'rest_framework',
    'django_filters',
    'interfaces.apps.InterfaceConfig',
    'projects.apps.ProjectConfig'
]

# DRF配置信息
REST_FRAMEWORK = {
    
    
    # 默认响应渲染类
    'DEFAULT_RENDERER_CLASSES': (
        # json渲染器为第一优先级
        'rest_framework.renderers.JSONRenderer',
        # 可浏览的API渲染器为第二优先级
        'rest_framework.renderers.BrowsableAPIRenderer',
    ),
    # 过滤和排序引擎配置
    'DEFAULT_FILTER_BACKENDS': ['rest_framework.filters.OrderingFilter',
                                'django_filters.rest_framework.backends.DjangoFilterBackend']
    # 默认分页引擎
    # 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'DEFAULT_PAGINATION_CLASS': 'utils.pagination.PageNumberPaginationManual',
    # --设置每页展示条数
    'PAGE_SIZE': 3

}

  • 自定义分页器
# utils.pagination.py

from rest_framework.pagination import PageNumberPagination


class PageNumberPaginationManual(PageNumberPagination):
    page_query_param = 'page_num'
    page_size_query_param = 'page_size'
    page_size = 10
    max_page_size = 50
# -*-coding:utf-8 -*-

from rest_framework.response import Response
from rest_framework import status, filters
from rest_framework.generics import GenericAPIView
from django_filters.rest_framework.backends import DjangoFilterBackend
from projects.models import Projects
from projects.serializer import ProjectModelSerializer
from utils.pagination import PageNumberPaginationManual


# 1. 需要继承自GenericAPIView
class ProjectList(GenericAPIView):
    # 2.指定查询集
    queryset = Projects.objects.all()
    # 3. 指定序列化器类
    serializer_class = ProjectModelSerializer

    # 排序
    # --1. 在类视图中指定过滤引擎,也可在全局settings.py中指定.一般使用全局设置
    # filter_backends = [filters.OrderingFilter]

    # --2. 指定需要排序的字段
    ordering_fields = ['id', 'pj_name', 'pj_leader']

    # 过滤
    # --1. 在类视图中指定过滤引擎,一般使用全局设置
    # filter_backends = [DjangoFilterBackend]

    # --2. 指定需要过滤的字段
    filterset_fields = ['id', 'pj_name', 'pj_leader']

    # 分页
    # --1. 在类视图中指定分页引擎,也可在全局settings.py中指定
    pagination_class = PageNumberPaginationManual

    def get(self, request):
        """
        http排序请求:http://127.0.0.1:8000/projects/?ordering=-id
        httpie过滤请求:http :8000/projects/ id==23
        """
        # 动态获取查询集
        projects = self.get_queryset()
        # 过滤查询集
        projects = self.filter_queryset(projects)
        # 排序过滤之后进行分页
        page = self.paginate_queryset(projects)
        if page is not None:
            serializer = self.get_serializer(instance=page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(instance=page, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

    def post(self, request):
        serializer = self.get_serializer(data=request.data)
        try:
            serializer.is_valid(raise_exception=True)
        except Exception as e:
            return Response(serializer.errors)
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)


# 1. 需要继承自GenericAPIView
class ProjectDetail(GenericAPIView):

    # 2.指定查询集
    queryset = Projects.objects.all()
    # 3. 指定序列化器类
    serializer_class = ProjectModelSerializer

    # 默认参数为pk,可以自定义
    lookup_field = 'id'

    def get(self, request, id):
        """
        模型类继承自GenericAPIView后,无需定义get_object方法
        """
        project = self.get_object()
        serializer = self.get_serializer(instance=project)
        return Response(serializer.data, status=status.HTTP_200_OK)

    def put(self, request, id):
        """
        httpie模拟请求:http PUT :8000/projects/12 pj_name='项目0091' pj_leader="张三" pj_developer='李四' pj_tester='王五' pj_app_name='测试应用' pj_app_version='1.0' pj_desc='demo desc'
        """
        project = self.get_object()
        serializer = self.get_serializer(instance=project, data=request.data)
        try:
            serializer.is_valid(raise_exception=True)
        except Exception as e:
            return Response(serializer.errors)
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    def delete(self, request, id):
        """
        httpie模拟请求:http DELETE :8000/projects/12
        """
        project = self.get_object()
        project.delete()
        return Response(None,  status=status.HTTP_204_NO_CONTENT)


猜你喜欢

转载自blog.csdn.net/qq_25672165/article/details/119613790