restframework 序列化和反序列化外键

前言

  • 这是博主第一次接触学习restframework框架,很多知识点零散不系统,在这不建议将此文作为指导方向。
  • 在此文讲解前,不会说明安装和配置信息,大家可以百度如何安装restframework,并自行安装成功就行。
  • 在此会讲解几种序列化和反序列化的方法,表的设计是一对多结构。

代码实现

序列化

首先我们在models下新建两个模型类

class User(SoftDeleteMode):
    GENDER_CHOICES = (
        ('1', '普通会员'),
        ('2', 'VIP会员')
    )
    name = models.CharField(max_length=100, verbose_name='昵称')
    phone = models.CharField(max_length=11, verbose_name='手机号', unique=True)
    password = models.CharField(max_length=255, verbose_name='密码')
    level = models.CharField(max_length=20, choices=GENDER_CHOICES, verbose_name='用户身份')

    class Meta:
        db_table = 'user'
        verbose_name = '用户表'
        app_label = 'polls' # 标记是属于哪个app的models,该属性常用于models的分层
        ordering = ['-id']  # 根据id倒序排列

    # 调用时返回自身的属性,不然都是显示xx object
    def __str__(self):
        return self.name


class BookInfo(SoftDeleteMode):
    title = models.CharField(max_length=20, verbose_name='名称')
    read = models.IntegerField(default=0, verbose_name='阅读量')
    comment = models.IntegerField(default=0, verbose_name='评论量')
    author = models.ForeignKey(User, on_delete=models.CASCADE, error_messages={"does_not_exist": "作者不存在"}) # 外键

    class Meta:
        db_table = 'tb_books'  # 指明数据库表名
        verbose_name = '图书'  # 在admin站点中显示的名字
        app_label = 'polls'  # app_lable的值为APP的名称,这样就可以将models定义到多个文件中了。

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

每个模型定义一个serializers.ModelSerializer

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['id', 'name', 'phone', 'level']


class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = BookInfo
        fields = ['id', 'title', 'read', 'comment','author']

通过postman请求我们的接口可以看到,author作为外键序列化后,返回的是User里的id。(忽略字段_create_time和_update_time)

如果我们想要返回具体外键里的值,应该怎么看呢。

  • 第一种方法: 在Meta中定义一个深度depth=1
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = BookInfo
        # 取出所有的字段
        fields = ['id', 'title', 'read', 'comment','author']
        depth = 1
  • 实现效果,可以看到会把外键相关的表数据序列化出来,而且是不可控的把表数据字段读了出来。但我们可能并不需要那么多的数据,包括用户密码等字段。

  • 第二种方法: 我们定义一个get_author()方法
class BookSerializer(serializers.ModelSerializer):
    author = serializers.SerializerMethodField() 

    class Meta:
        .....
        
    
    # 在BookSerializer中我们定义一个方法,获取外键对应的数据
    def get_author(self, obj):
        authors_query_set = obj.author  # 拿到所有作者信息 (obj是User对象)
        return [{"id": authors_query_set.id, "name": authors_query_set.name}]

  • 实现效果: 可以看到,按照我们定义的方法返回了值,需要什么数据可以在get_author中添加即可,想要反序列化{"author": 1}作为外键添加时,不得有depth=1

反序列化

可以在serializers.ModelSerializer中定义与author字段相同的属性,并实例化serializers.PrimaryKeyRelatedField对象

class BookSerializer(serializers.ModelSerializer):
    # 必须要传的参数,queryset查询集,这里我们的主表是User表,所以定义了User的查询集
    # error_messages: 错误提示信息,如果对象未找到对应的key:does_not_exist
    author = serializers.PrimaryKeyRelatedField(queryset=User.objects.all(), error_messages={"does_not_exist": "作者不存在"})
    
    class Meta:
        model = BookInfo
        fields = ['id', 'title', 'read', 'comment']
    
    def get_author(self, obj):
        authors_query_set = obj.author  # 拿到所有作者信息
        return [{"id": authors_query_set.id, "name": authors_query_set.name}]
    

实现效果:

  • 添加成功

  • 添加失败

原文地址:https://www.cnblogs.com/se7enjean/p/13186675.html