四方显神

导航

Django开发笔记(十二)DRF PUT更新部分数据 字段校验

 一、查看单条数据

定义访问路径:

(Django3.0版本,前面版本的查询条件不是这样)

path('retrieve/<int:id>',BookEditView.as_view())

views.py:

class BookEditView(APIView):
    # 查询单条数据
    def get(self,request,id):
        book = Book.objects.filter(id=id).first()
        ret = BookSerializers(book) # 拿到结果进行序列化
        return Response(ret.data)

二、更新数据(PUT请求,更新部分字段)

这里有个疑问哈,可能我学得还是有点囫囵了,有些东西基础不牢地动山摇

class BookEditView(APIView):
    # 查询单条数据
    def get(self,request,id):
        book = Book.objects.filter(id=id).first()
        ret = BookSerializers(book) # 拿到结果进行序列化
        return Response(ret.data)

    # 更新数据 这里我没搞明白,是put自动走update那个方法,post自动走create吗?
    def put(self,request,id):
        book = Book.objects.filter(id=id).first()
        # 第一个参数instance是实例化对象也就是book,
        # 第二个参数书data携带我们要更新的数据,第三个参数是partial=True意思是允许部分更新
        serializer = BookSerializers(book,data=request.data,partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.validated_data)
        else:
            return Response(serializer.errors)

三、DRF校验

需求1:对个别字段进行更个性化的校验

需求2:对字段进行联合校验

两种方法:(都是在serializer文件下写校验方法的)

validate_字段名 对单个字段进行校验;validate进行联合校验

DRF提供校验器,自定义校验器进行校验(要在字段上加上参数validators=[] 如:title = serializers.CharField(max_length=32,validators=[my_validate]) 
serializer.py文件:
from rest_framework import serializers
from .models import Book


class PublisherSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    title = serializers.CharField(max_length=32)


class AuthorSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    name = serializers.CharField(max_length=32)


# 方法2:实际上,DRF也给我们提供了一个自己定义的验证器,而且这个校验器权重更高,比在类里设置的validate_字段 权重要高
def my_validate(value):
    if "敏感信息" in value.lower():
        raise serializers.ValidationError("不能含有敏感信息")
    return value


class BookSerializers(serializers.Serializer):
    id = serializers.IntegerField(required=False)  # required = false就是不需要校验,那么在反序列化的时候就可以不传
    title = serializers.CharField(max_length=32,validators=[my_validate]) # 这个validators参数就是我们定义好的校验器
    CHOICES = ((1, 'Python'), (2, 'Go'), (3, 'Linux'))
    # 这里和模型类定义有所不用了,多了一个source
    # read_only = True 就是说我只在序列化的时候用,前端展示的时候用,反序列化的时候用的是另一个w_category
    category = serializers.ChoiceField(choices=CHOICES, source="get_category_display", read_only=True)
    # write_only=True 意思是只反序列化的时候用,也就是说序列化的时候根本不会动这个字段,那前端传数据的时候就要约定传的是这个W_category了
    w_category = serializers.ChoiceField(choices=CHOICES, write_only=True)
    pub_time = serializers.DateField()
    # 外键的反序列化 和上面的category处理方法一样
    publisher = PublisherSerializer(read_only=True)
    publisher_id = serializers.IntegerField(write_only=True)
    author = AuthorSerializer(many=True, read_only=True)  # 这个many参数不要忘了
    author_list = serializers.ListField(write_only=True)

    def create(self, validate_data):
        book = Book.objects.create(title=validate_data["title"],
                                   category=validate_data["w_category"],
                                   pub_time=validate_data["pub_time"],
                                   publisher_id=validate_data["publisher_id"])
        book.author.add(*validate_data["author_list"]) # 对前端传的author列表进行解包
        return book

    def update(self,instance,validate_data):
        instance.title = validate_data.get("title",instance.title) # 取title,如果取不到,就用instance.title
        instance.category = validate_data.get("category", instance.category)
        instance.pub_time = validate_data.get("pub_time", instance.pub_time)
        instance.publisher_id = validate_data.get("publisher_id", instance.publisher_id)
        # many to many 字段我们要判断一下
        if validate_data.get("author_list"):
            instance.author.set(validate_data["author_list"])
        instance.save()
        return instance

   # 校验方法1: # DRF提供的对单独字段的校验 # 方法名是 validate_字段 参数value是字段传过来的值 def validate_title(self,value): if "python" not in value.lower(): # 抛异常,异常信息自定义 raise serializers.ValidationError("标题必须含有python") return value # 对多个字段进行联合校验 全局性的 def validate(self, attrs): if attrs["w_category"]==1 and attrs["publisher_id"]==1: return attrs else: raise serializers.ValidationError("不满足我们的全局校验条件")

 

posted on 2024-03-20 15:49  szdbjooo  阅读(45)  评论(0)    收藏  举报