首页 > 解决方案 > 如何为具有外键的模型定义序列化程序(不指向 pk 字段,而是指向唯一字段)?

问题描述

我正在使用 django 休息框架

有以下两种模式

class Service(ResourceModelBase):
    _id = models.UUIDField(unique=True, null=False, default=uuid.uuid1)
    access_key = models.CharField(max_length=200, unique=True, null=False)
    cluster = models.OneToOneField(Cluster, to_field='_id')

class Cluster(ResourceModelBase):
    _id = models.UUIDField(unique=True, null=False, default=uuid.uuid1)
    name = models.CharField(max_length=200, unique=True, null=False)

服务有一个外键指向集群唯一键_id字段请注意_id不是主键,它是唯一键。这对我后面的问题很重要

然后我为服务模型定义了一个序列化程序,这样我就可以创建和获取服务数据。

class ServiceSerializer(serializers.ModelSerializer):
    cluster_id = serializers.SlugRelatedField(queryset=models.Cluster.objects.all(), slug_field='_id')
    class Meta:
        model = models.RGW
        fields = ('_id', 'access_key', 'cluster_id')

请注意,我将cluster_id 定义为 SlugRelatedField 而不是 PrimaryKeyRelatedField。

这样做的原因是我想向 cluster_id 传递一个参数来创建服务。

如果我将 cluster_id 定义为主键相关字段,框架倾向于认为 cluster_id 外键指向主键列。但就我而言,事实并非如此。它指向一个唯一的关键字段。

所以我使用 SlugRelatedField(我不确定这是否是正确的做法)。但另一个问题出现了。

当我将数据发送到序列化器时。我发送的数据如下:

{'cluster_id': 'ef3f70cac9e111e89fd1f000ac192ced', 'access_key': 'aaaa'}

但是经过 serailzier 验证后的数据是

serializer.validated_data
OrderedDict([('access_key', 'aaaa'), ('cluster_id', <Cluster: Cluster object (2)>)])

由于某种原因,cluster_id 被转换为集群对象。所以如果我跑

 serializer.save(serializer.validated_data) 

这将导致错误。

当然我可以重写保存方法。但我只想知道最好的方法是什么。我觉得我以错误的方式使用框架

标签: djangodjango-rest-framework

解决方案


推荐阅读