django框架学习三:djangorestframework中序列化器的优化:添加单字段、多字段、自定义函数的校验

serializer.py文件的优化,此阶段添加了对字段的校验以及序列化器自带的create方法和update方法:

# -*- coding: utf-8 -*-
# @Time    : 2020/3/10 20:07
# @Author  : benben
# @File    : serializer.py
from rest_framework import serializers
from rest_framework.validators import UniqueValidator

from .models import Projects

# 创建自定义校验器
# 第一个参数为字段的值


def is_unique_project_name(name):
    if '项目' not in name:
        raise serializers.ValidationError('项目名称中必须包含"项目"')


class ProjectsSerializer(serializers.Serializer):
    id = serializers.IntegerField(label="ID", read_only=True)
    name = serializers.CharField(label="项目名称", max_length=50, min_length=5, help_text="项目名称",
                                 validators=[UniqueValidator(queryset=Projects.objects.all(), message="项目名称已存在"),
                                             is_unique_project_name])
    leader = serializers.CharField(label="负责人", max_length=50, help_text='负责人')
    tester = serializers.CharField(label="测试人员", max_length=50, help_text="测试人员")
    programer = serializers.CharField(label="开发人员", max_length=50, help_text="开发人员")
    publish_app = serializers.CharField(label="发布应用", max_length=100, help_text="发布应用")
    desc = serializers.CharField(label="简要描述", allow_null=True, allow_blank=True, default='', help_text="简要描述")

    # 单字段校验器
    # validate_字段名
    # 字段定义时的限制(包含validators列表条目从左到右进行校验) -> 单字段的校验(validate_字段名) -> 多字段联合校验(validate)
    def validate_name(self, value):
        if not value.endswith("项目"):
            raise serializers.ValidationError('项目名称必须以"项目"结尾')
        return value

    # 多字段校验器
    def validate(self, attrs):
        if "benben" not in attrs['tester'] and "benben" not in attrs["leader"]:
            raise serializers.ValidationError("benben必须是项目负责人或者测试人员")
        return attrs

    # 新增项目
    def create(self, validated_data):
        return Projects.objects.create(**validated_data)

    # 修改项目
    def update(self, instance, validated_data):
        instance.name = validated_data['name']
        instance.leader = validated_data['leader']
        instance.tester = validated_data['tester']
        instance.programer = validated_data['programer']
        instance.publish_app = validated_data['publish_app']
        instance.desc = validated_data['desc']
        instance.save()
        return instance

views.py文件优化:使用serialzer.save(),自动调用序列化器中的create方法和update()方法:

import json
from django.views import View
from django.http import JsonResponse, Http404
from .models import Projects
from .serializer import ProjectsSerializer


class ProjectsList(View):
    def get(self, request):
        # 从数据库中读取所有的项目
        projects = Projects.objects.all()
        # 序列化输出, 将查询集传给序列化器的instance参数
        # 由于是查询多条记录,所以需要设置many=True
        serializer = ProjectsSerializer(instance=projects, many=True)
        # 由于返回的是嵌套字典的列表,所以需要设置safe=False
        return JsonResponse(data=serializer.data, safe=False)

    def post(self, request):
        # 获取前端提交的信息
        json_data = request.body.decode("utf-8")
        # 将json字符串转换为python中的dict
        python_data = json.loads(json_data)
        # 反序列化
        serializer = ProjectsSerializer(data=python_data)
        # 校验前端数据
        try:
            serializer.is_valid(raise_exception=True)
        except Exception as e:
            return JsonResponse(serializer.errors)
        # 校验成功之后的数据, 可以使用validated_data属性来获取
        # 1. 如果在创建序列化器对象的时候, 只给data传参, 那么调用save()方法,
        # 实际调用的就是序列化器对象的create()方法
        # serializer.save(user="孤鹰", age=16)
        serializer.save()
        # 3. 将模型类对象转化为字典, 然后返回
        # 序列化
        return JsonResponse(serializer.data, status=201)


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

    def get(self, request, pk):
        project = self.get_object(pk)
        serailzer = ProjectsSerializer(instance=project)
        return JsonResponse(serailzer.data)

    def put(self, request, pk):
        project = self.get_object(pk)
        # 获取前端提交的信息
        json_data = request.body.decode("utf-8")
        # 将json字符串转换为python中的dict
        python_data = json.loads(json_data)
        serialzier = ProjectsSerializer(instance=project, data=python_data)
        # 校验前端数据
        try:
            serialzier.is_valid(raise_exception=True)
        except Exception as e:
            return JsonResponse(serialzier.errors)
        # 更新项目
        # 在创建序列化器对象时, 如果同时给instance和data传参
        # 那么调用save()方法, 会自动化调用序列化器对象的update
        serialzier.save()
        return JsonResponse(serialzier.data, status=201)

    def delete(self, request, pk):
        project = self.get_object(pk)
        project.delete()
        return JsonResponse(None, safe=False, status=204)

models.py文件和urls.py文件代码未更新,继续使用上一篇文章中的代码即可!

posted @ 2020-03-13 23:46  奔奔-武  阅读(554)  评论(0编辑  收藏  举报