四十、整理嵌套序列化器的使用方法

本文介绍了在Django中处理模型间一对多关系时如何使用嵌套序列化器来展示接口关联的测试用例和测试场景。通过在接口模型的序列化器中引用测试用例的序列化器,以及利用反向关联属性(如`teststep_set`),可以方便地获取并展现接口关联的所有测试用例信息。此外,还展示了在测试场景模型中如何通过类似的方式处理中间表的序列化,以获取步骤的详细信息。
摘要由CSDN通过智能技术生成

一、常见用法

(1)用法1

接口模型、测试用例模型

# 接口模型
class Interface(models.Model):
    """接口表"""
    CHOICES = [
        ('1', '项目接口'),
        ('2', '三方接口')
    ]
    project = models.ForeignKey(Project, on_delete=models.CASCADE, help_text='项目id',
                                verbose_name='项目id',
                                related_name='interfaces')
    name = models.CharField(max_length=50, help_text='接口名称', verbose_name='接口名')
    url = models.CharField(max_length=200, help_text='接口路径', verbose_name='接口路径')
    method = models.CharField(max_length=50, help_text='请求方法', verbose_name='请求方法')
    type = models.CharField(verbose_name='接口类型', help_text='接口类型',
                            max_length=40, choices=CHOICES, default='1')

    def __str__(self):
        return self.url

    class Meta:
        db_table = 'tb_interface'
        verbose_name = '接口表'
        verbose_name_plural = verbose_name


# 测试用例
class TestStep(models.Model):
    """用例表"""
    title = models.CharField(max_length=50, help_text='用例名称', verbose_name='用例名')
    # 一个接口对应多个用例, 一个用例对应一个接口
    interface = models.ForeignKey('projects.Interface', on_delete=models.CASCADE, help_text='接口', verbose_name='接口')
    headers = models.JSONField(help_text='请求头', verbose_name='请求头', default=dict, blank=True)
    request = models.JSONField(help_text='请求信息', verbose_name='请求信息', default=dict, blank=True)
    file = models.JSONField(help_text='上传的文件参数', verbose_name='上传的文件', default=list, blank=True)
    setup_script = models.TextField(help_text='前置脚本', verbose_name='前置脚本', default=setup_script, blank=True)
    teardown_script = models.TextField(help_text='后置脚本', verbose_name='用例后置脚本 ', default=teardown_script,
                                       blank=True)

    def __str__(self):
        return self.title

    class Meta:
        db_table = 'tb_test_step'
        verbose_name = "测试步骤表"
        verbose_name_plural = verbose_name

嵌套序列化器:

先搞清楚2个模型之间的关系,这里 Interface模型,也就是接口模型,跟测试用例其实是一对多的关系,一个接口可能有多个测试用例,一个测试用例只有一个接口。

那这个时候我想知道我这个接口关联了哪几个测试用例怎么办?(也就是说有几个测试用例涉及到了这个接口),那我们接口模型中又没有用例这个字段?怎么办?

我们需要新增一个字段 steps ,这个字段的数据从哪里获取?我们看到用例模型中有interface字段外键关联接口模型,所以我们通过嵌套序列化器,source指定=teststep_set。

如果一个模型 TestStep 有一个外键关联到另一个模型 Interface,那么DRF会自动为TestStep模型生成一个名为teststep_set的反向关联属性,用于对TestStep模型进行反向查询。在嵌套序列化器中,我们可以使用这个反向关联属性来指定需要序列化的字段。

当一个模型定义了 ForeignKey 或者 ManyToManyField 字段时,Django 会自动为这个模型添加一个反向关联属性,这个属性的名称是由 Django 自动生成的,默认为关联模型的小写名称加上 _set。

class NestTestStepSerializer(serializers.ModelSerializer):
    """嵌套测试步骤序列化器"""

    class Meta:
        model = TestStep
        # 为啥只要id和title(前后端沟通交流)
        fields = ['id', 'title']


class InterfaceSerializer(serializers.ModelSerializer):
    """
    接口序列化器
    """
    steps = NestTestStepSerializer(source='teststep_set', many=True, read_only=True)

    class Meta:
        model = Interface
        fields = '__all__'

(2)用法2

接口模型、测试场景模型

# 用例表
class TestStep(models.Model):
    """用例表"""
    title = models.CharField(max_length=50, help_text='用例名称', verbose_name='用例名')
    # 一个接口对应多个用例, 一个用例对应一个接口
    interface = models.ForeignKey('projects.Interface', on_delete=models.CASCADE, help_text='接口', verbose_name='接口')
    headers = models.JSONField(help_text='请求头', verbose_name='请求头', default=dict, blank=True)
    request = models.JSONField(help_text='请求信息', verbose_name='请求信息', default=dict, blank=True)
    file = models.JSONField(help_text='上传的文件参数', verbose_name='上传的文件', default=list, blank=True)
    setup_script = models.TextField(help_text='前置脚本', verbose_name='前置脚本', default=setup_script, blank=True)
    teardown_script = models.TextField(help_text='后置脚本', verbose_name='用例后置脚本 ', default=teardown_script,
                                       blank=True)

    def __str__(self):
        return self.title

    class Meta:
        db_table = 'tb_test_step'
        verbose_name = "测试步骤表"
        verbose_name_plural = verbose_name



# 测试场景/套件 中间表
class SceneData(models.Model):
    """场景/套件数据,中间表"""
    step = models.ForeignKey('TestStep', help_text='步骤', verbose_name='步骤',
                             on_delete=models.PROTECT)
    scene = models.ForeignKey(TestScene, help_text='场景', verbose_name='场景', on_delete=models.PROTECT)
    sort = models.IntegerField(help_text='执行顺序', verbose_name='执行顺序',
                               blank=True)

    def __str__(self):
        return str(self.id)

    class Meta:
        db_table = 'tb_scene_data'
        verbose_name = "场景步骤"
        verbose_name_plural = verbose_name


setup_script = """
# 前置脚本(python):
# global_tools:全局工具函数
# data:用例数据
# env: 局部环境

# ENV: 全局环境
# db: 数据库操作对象
"""
teardown_script = """
# 后置脚本(python):
# global_tools:全局工具函数
# data:用例数据
# response:响应对象response
# env: 局部环境
# ENV: 全局环境
# db: 数据库操作对象
"""

序列化器:

场景中间表有 step用例、scene场景、sort执行顺序。我在场景中间表序列化器中新定义一个stepInfo,用来存储用例序列化器实例化出来的对象。

source='step',是啥意思?

因为第三张表中的step与 TestStep 是外键关联的,所以 NestTestStepSerializer用例序列化器 可以直接引用 别的模型中的字段。

class NestTestStepSerializer(serializers.ModelSerializer):
    """嵌套测试步骤序列化器"""

    class Meta:
        model = TestStep
        # 为啥只要id和title(前后端沟通交流)
        fields = ['id', 'title']


class TestSceneStepSerializer(serializers.ModelSerializer):
    """测试场景步骤序列化器"""
    # 这是一个额外的字段, source代表意思是指定源,告诉他你是哪个字段。
    stepInfo = NestTestStepSerializer(source='step', read_only=True)

    class Meta:
        model = SceneData
        fields = '__all__'

(3)用法3

我们要在学生信息界面展示出该学生的成绩,就需要关联到成绩外键,需要在学生的序列化器中调用成绩序列化器


class Student(models.Model):
    name = models.CharField(max_length=50, verbose_name="姓名")
    age = models.IntegerField(verbose_name="年龄")
    sex = models.BooleanField(default=False)
    class Meta:
        db_table = 'sch_student'
 
    def __str__(self):
        return self.name


class Achievement(models.Model):
    score = models.DecimalField(default=0, max_digits=4, decimal_places=1, verbose_name="成绩")
    student = models.ForeignKey(Student,on_delete=models.DO_NOTHING, related_name='s_achievement', db_constraint=False)
    course = models.ForeignKey(Course,on_delete=models.DO_NOTHING, related_name='c_achievement', db_constraint=False)
    create_dtime = models.DateTimeField(auto_created=datatime.now)
    class Meta:
        db_table = "sch_achievement"
 
    def __str__(self):
        return str(self.score)

class AchievementModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Achievement
        fields = "__all__"
 
class StudentModelSerializer(serializers.ModelSerializer):
    # 在序列化器中调用另一个序列化器,就是序列化器嵌套
    s_achievement = AchievementModelSerializer()
    class Meta:
        model = Student
        fields = ['id','name','s_achievement']

总结:

下面提到的一和多 就是表之间的关系是一对多还是多对一的意思。

第一个场景 是在一的一方去嵌套序列化器,所以source是用到多的一方的小写模型名+_set

第二个场景 是在多的一方去嵌套序列化器,source直接引用相关联的模型所对应的字段。

(4)用法4

(5)用法5

 

(6)用法6

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值