首页 > 其他分享 >drf快速编写接口

drf快速编写接口

时间:2023-02-02 21:23:17浏览次数:51  
标签:serializers name publish 接口 authors 编写 序列化 data drf

创建序列化类字段参数

from rest_framework import serializers
from app01.models import Book

举例:
class BooksSerializer(serializers.Serializer):
    name = serializers.CharField()
    price = serializers.IntegerField()
    emial = serializers.EmailField()
    
    publish_dict = serializers.DictField(read_only=True)
    authors_list = serializers.ListField(read_only=True)

    publish = serializers.CharField(write_only=True)
    authors = serializers.ListField(write_only=True)
    

常用字段可设置参数:
CharField:  字符串
  max_length	最大长度
  min_lenght	最小长度
  allow_blank	是否允许为空
  trim_whitespace	是否截断空白字符
  
  
IntegerField: 数字整型
	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页面时,显示的字段帮助提示信息
    
写入数据反序列化校验流程
    1.先效验字段参数设置校验,
    2.validators设置的方法
    3.局部钩子
    4.全局钩子

序列化类字段名展示修改source

# 重点:source可以指定序列化字段的名字
	  -自有字段,直接写字段名字
    	-name_real = serializers.CharField(max_length=8, source='name')
    -关联字段,一对多的关联,直接点
    	-publish = serializers.CharField(source='publish.name')
    -多对多,搞不了,source不能用
    	-authors=serializers.CharField(source='authors.all')
      
 这样可以隐藏数据库字段名

 name_real = serializers.CharField(source='name')
 前端收到的是name_real字段数据,但数据其实还是数据库里面的name字段

 

序列化之获取数据-read

序列化之高级获取定制字段类型:

方法1:在序列化类中使用 .SerializerMethodField()方法

模型类不用改,相当于把获取到的数据到这里二次加工后返回给前端


# 定制关联字段的显示形式
	-一对多的,显示字典  
  -多对多,显示列表套字典

class BookSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=8)
    price = serializers.CharField()

    publish_detail = serializers.SerializerMethodField()
    # publish_detail字段需要直接给前端返回所有的信息,已字典的形式
    # 所以可以是用.SerializerMethodField()方法,搭配def get_publish_detail
    # 让这个字段返回的是我们自定义de

    def get_publish_detail(self, obj):
      # get_名字一定要跟上面的一直
        return {'name': obj.publish.name, 'addr': obj.publish.addr}

    author_list = serializers.SerializerMethodField()

    def get_author_list(self, obj):
        l = []
        for author in obj.authors.all():
            l.append({'name': author.name, 'phone': author.phone})
        return l

方法2:models模型类中编写方法(推荐)

序列化类只需要更改一下接受的数据类型即可

直接在模型类中 编写方法

class Book(models.Model):
    name = models.CharField(max_length=12)
    price = models.CharField(max_length=10)

    publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
    authors = models.ManyToManyField(to='Authors')

    @property
    def publish_dict(self):
      # 编写方法 直接将需要的数据格式返回
        return {'name': self.publish.name, 'addr': self.publish.address}

    @property
    def authors_list(self):
      # 编写方法 直接将需要的数据格式返回
        l1 = []
        for author in self.authors.all():
            l1.append({'name': author.name, 'addr': author.address})
        return l1
      
      
序列化类中:
  class BooksSerializer(serializers.Serializer):
    name = serializers.CharField()
    price = serializers.CharField()

    publish_dict = serializers.DictField(read_only=True)
    # read_only=True只有序列化时执行
    # 这里的变量名对应模型类中的方法
    # 接受的数据类型对象模型类中返回的数据类型 字典类型
    authors_list = serializers.ListField(read_only=True)
    # 这里的变量名对应模型类中的方法
    # 接受的数据类型对象模型类中返回的数据类型 列表类型
    
    
这样前端得到的就是:

  {
    "code": 100,
    "msg": "获取成功",
    "result": [
        {
            "name": "完美世界",
            "price": "122",
            "publish_dict": {
                "name": "完美出版社",
                "address": "北京"
            },
            "authors_list": [
                {
                    "name": "吴彦祖",
                    "phone": "18838228881"
                },
                {
                    "name": "张无忌",
                    "phone": "18838228881"
                }
            ]
        }
            ]
        }
 

反序列化之新增数据 -write

前端传入数据格式,json :{name:红楼梦,price:19,publish:1,authors:[1,2]}
# 视图类中 正常编写代码

class BookView(APIView):
    def post(self, request):
        ser = BookSerializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code': 100, 'msg': '新增成功'})
        else:
            return Response({'code': 101, 'msg': ser.errors})
          
    def delete(self, request, id):
        Books = Book.objects.filter(pk=id).first()
        Books.authors.clear()
        Books.delete()
        return Response({'msg': '删除成功'})

          
# 序列化中中需要改变代码
  class BookSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=8)
    price = serializers.CharField()

    # 只用来做序列化   只读  read_only
    publish_detail = serializers.DictField(read_only=True)
    author_list = serializers.ListField(read_only=True)

    # 只用来做反序列化  只写  write_only
    publish = serializers.CharField(write_only=True)
    authors = serializers.ListField(write_only=True)
		# 根据前端传入的数据类型来设置,由于authors字段前端传入的是一个列表,所以我们也使用列表接收
    
    def create(self, validated_data):
      # 新增数据需要些create方法
        book = Book.objects.create(name=validated_data.get('name'),                    price=validated_data.get('price'), 
		publish_id=validated_data.get('publish'))
        # 创建一个book对象 字段数据都从validated_data中取
        # publish_id外键字段

        book.authors.add(*validated_data.get('authors'))
        # book.author多对多关系的第三章表,由于是自动创建的,可以使用add方法
        # validated_data.get('authors') = [1,2]
        # *validated_data.get('authors')使用一个*语法将列表打散 传入了add方法中
        return book

反序列化之修改数据

	-前端传入的数据格式:{name:红楼梦,price:19,publish:1,authors:[1,2]}
新增一个路由地址 传送url接收id
 class BookDetailView(APIView):
    def put(self, request, pk):
        book = Book.objects.filter(pk=pk).first()
        ser = BookSerializer(data=request.data, instance=book)
        # instance=book 需要修改的对象,data=request.data,前端传入的数据
        if ser.is_valid():
            ser.save()
            return Response({'code': 100, 'msg': '修改成功'})
        else:
            return Response({'code': 101, 'msg': ser.errors})
          
          
序列化类中:重写update方法
	def update(self, instance, validated_data):
        # validated_data 校验过后的前端传入的数据
        instance.name = validated_data.get('name')
        instance.price = validated_data.get('price')
        instance.publish_id = validated_data.get('publish')

        # 关于第三张表  
        instance.authors.clear()
        # 先清空第三章表关系
        instance.authors.add(*validated_data.get('authors'))
        # 然后再重新添加第三章表关系
        instance.save()
        return instance
      
      

反序列化时字段校验

class BooksSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=6,min_length=3,allow_blank=False,error_messages={
        'max_length':'太长了',
        'min_length':'太短了',
        'allow_blank':'不能为空'
    })
    
    def validate_name(self, name):
        if name == 'moon':
            raise ValidationError('不可以叫这个')
        else:
            return name
          
# 可以使用字段参数限制,也可以使用钩子函数限制

最方便的ModelSerializer使用

ModelSerializer可以帮助我们快速实现 序列化反序列化接口

# 视图类函数 无需更改:

class BooksView(APIView):
    def get(self, request):
        books = Book.objects.all()
        ser = BookSerializer(instance=books, many=True)
        return Response({'code': 100, 'msg': '获取成功', 'result': ser.data})

    def post(self, request):
        book_obj = BookSerializer(data=request.data)
        if book_obj.is_valid():
            book_obj.save()
            return Response({'code': 100, 'msg': '新增成功', 'result': book_obj.data})
        else:
            return Response({'code': 101, 'msg': book_obj.errors})

          
          
# 序列化类中 需要继承ModelSerializer

from rest_framework import serializers
from .models import Book
from rest_framework.serializers import ValidationError


class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        #该 序列化类关联的表格
        fields = ['id', 'name', 'price', 'publish_dict', 'authors_list', 'publish', 'authors']
        # 设置需要展示表字段内容

        # 方式一:字段添加约束条件,控制字段读写方式
        extra_kwargs = {'publish': {'write_only': True},
                        'authors': {'write_only': True},
                        'publish_dict': {'read_only': True},
                        'authors_list': {'read_only': True}}
        
    # 一定在写在class Meta:类外面
    name = serializers.CharField(max_length=4, error_messages={'max_length': '太长了'})
   # 方式二:也是给序列化字段添加约束条件,改相当于重写了字段要求 一定要写在类外面

    publish_dict = serializers.SerializerMethodField()
    # 构建字段返回内容
    def get_publish_dict(self, obj):
        return {'name': obj.publish.name, 'addr': obj.publish.address}

    author_list = serializers.SerializerMethodField(read_only=True)
		# 构建字段返回内容
    def get_author_list(self, obj):
        l = []
        for i in obj.authors.all():
            l.append({'name': i.name, 'phone': i.address})
        return l
        
        
    # 钩子函数
    def validate_name(self, name):
        if name.startswith('sb'):
            raise ValidationError('不能sb')
        else:
            return name
          
# 这样就完成了 接口 读 新增 修改 
# 删除不涉及序列化 直接在视图类中写即可

标签:serializers,name,publish,接口,authors,编写,序列化,data,drf
From: https://www.cnblogs.com/moongodnnn/p/17087448.html

相关文章