Bob's Blog

Python、Web开发、测试框架、自动化平台、机器学习等

返回上页首页

Django DRF根据model的字段动态限制另一字段的内容



在定义model时,有时有这种需求:将该model的某一字段的值限定在一定条件内,并且依据该model里的另一字段来限定。比如我现在创建测试集,需要选择多个测试脚本,但是我必须将测试脚本动态地限定在和测试集同样的项目里。

其实这个问题不是django restframework才有的,django都会有这种需求,只是这里用django restframework时解决了。

先看最初的model:

class TestSuite(models.Model):

    name = models.CharField(max_length=100)
    project = models.ForeignKey(Project, on_delete=models.CASCADE)
    script = models.ManyToManyField(Script)
    create_time = models.DateTimeField(default=timezone.now)
    update_time = models.DateTimeField(default=timezone.now)

假设project有A和B两个,分别对应着多个不同的script。那么在创建test suite时,就应该限制用户不能去选择非当前project的script。比如test suite的project字段是A,就不能让用户选择到B的script,也不能成功提交。

如果不是动态地限定的话,实现是比较简单的,可以用limit_choices_to:

# 限定script只能选择project id为2的项目里
script = models.ManyToManyField(Script, limit_choices_to={'project': 2})

如果要动态地限定,script跟随project字段来限定,那么实现会麻烦一些,当然下面这种是不可行的:

# 这是不可行的
script = models.ManyToManyField(Script, limit_choices_to={'project': project})

对于django restframework来说,可以在serializers里加上自定义的校验。加上对应的函数,比如校验script就用validate_script,当script的project值匹配上test suite的project的值,那么就通过,否则就抛出错误提示400.

class TestSuiteSerializer(serializers.ModelSerializer):

    def validate_script(self, value):
        script_match_project = True
        project = self.context['request'].data["project"][0]
        for v in value:
            if v.project_id != int(project):
                script_match_project = False
                break
        if script_match_project:
            return value
        else:
            raise serializers.ValidationError("Cannot select scripts from another project")

    class Meta:
        model = TestSuite
        fields = "__all__"

重新启动后便能看到效果,选择不匹配的project是无法成功保存的,只有选择了匹配的project才行。该需求得到解决。

下一篇:  Django Restframework自定义修改局部的分页设置
上一篇:  scrcpy在Mac上的使用

共有0条评论

添加评论

暂无评论