Django REST框架 - 嵌套序列化器验证?

8

所以我有以下这些模型:

class Leaderboard(models.Model):
    pass


class Column(models.Model):
    leaderboard = models.ForeignKey(Leaderboard, related_name="columns", on_delete=models.CASCADE)
    related_columns = models.ManyToManyField(self)
    index = models.PositiveIntegerField()

还有像这样的序列化器:

class ColumnSerializer(ModelSerializer):
    related_columns = serializers.PrimaryKeyRelatedField(queryset=Column.objects.all(), many=True)

    class Meta:
        model = Column
        fields = ('leaderboard', 'related_columns', 'index',)


class LeaderboardSerializer(ModelSerializer):
    children = ColumnSerializer(many=True)

    class Meta:
        model = Leaderboard
        fields = ('columns',)

我希望能够验证添加到 ColumnSerializerrelated_columns 是否已经属于其父级 Leaderboard。在创建 ColumnSerializer 时,我尝试访问 Leaderboard 或 Leaderboard ID (例如通过手动指定 fields 中的 id)进行验证,但是在 Column 初始化之前,LeaderboardSerializer 未初始化,因此无法验证细节。

基本上,我想要修改 queryset=Column.objects.all()queryset=self.instance.leaderboard.columns.all()

然而,在 Column 中我无法访问 Leaderboard。例如,在 ColumnSerializer 中访问 self.parent.instance/initialNone,直到在 Leaderboard.validate_columns() 中。我想到的一件事是只需在 Leaderboard 端执行验证,但是我仍然认为应该“可行”在 Column 中进行此验证,以防以后我想要直接编辑它们,而不必先通过 Leaderboard


我认为这就是基本验证方法的作用。由于您的related_columns验证需要另一个字段的知识,请在那里进行检查。 - kevswanberg
你找到了一种方法来做这件事吗?我也在考虑根据父级信息验证子序列化程序。 - FMCorz
@FMCorz在下面发布了我的答案! - Eric Carmichael
1个回答

0
这是我解决这个问题的方法:
def validate_columns(self, columns):
    if not columns:
        raise serializers.ValidationError("Leaderboards require at least 1 column")

    # Make sure all column indexes are unique
    indexes = [column['index'] for column in columns]
    if len(set(indexes)) != len(columns):
        raise serializers.ValidationError("Columns must have unique indexes!")

    # Make sure all column keys are unique
    keys = [column["key"] for column in columns]
    if len(set(keys)) != len(columns):
        raise serializers.ValidationError("Columns must have unique keys!")

    # Validate that column.computation_indexes points to valid columns
    for column in columns:
        if 'computation_indexes' in column and column['computation_indexes']:
            for index in column['computation_indexes'].split(","):
                try:
                    if int(index) not in indexes:
                        raise serializers.ValidationError(f"Column index {index} does not exist in available indexes {indexes}")
                except ValueError:
                    raise serializers.ValidationError(f"Bad value for index, should be an integer but received: {index}.")

    return columns

我确保列在它们的键和索引中是唯一的,并且它们所引用的列也存在。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接