Django序列化程序,嵌套关系和get_or_create

问题描述 投票:0回答:1

我一直在讨论这个问题一段时间了。我有两个模型:收购和RawDatas。

每个RawData都有一个Acquisition,但许多RawDatas可以拥有相同的Acquisition。

我想在创建RawDatas时自动创建或获取Acquisition的实例。我希望能够使用序列化器获得所有信息。

class Acquisitions(models.Model):
    class Meta:
        unique_together = (('implant', 'beg_acq', 'duration_acq'),)

    id = models.AutoField(primary_key=True)
    implant = models.ForeignKey("Patients", on_delete=models.CASCADE)
    beg_acq = models.DateTimeField("Beggining date of the acquisition")
    duration_acq = models.DurationField("Duration of the acquisition")

class RawDatas(models.Model):
    class Meta:
    unique_together = (('acq', 'data_type'),)

    id = models.AutoField(primary_key=True)
    acq = models.ForeignKey("Acquisitions", on_delete=models.CASCADE)
    data_type = models.CharField(max_length=3)
    sampling_freq = models.PositiveIntegerField("Sampling frequency")
    bin_file = models.FileField(db_index=True, upload_to='media')

我的序列化器是这些:

class AcquisitionSerializer(serializers.ModelSerializer):
    class Meta:
        model = Acquisitions
        fields = ('id', 'implant', 'beg_acq', 'duration_acq')

class RawDatasSerializer(serializers.ModelSerializer):
    acq = AcquisitionSerializer()

    class Meta:
        model = RawDatas
        fields = ('id', 'data_type', 'sampling_freq', 'bin_file', 'acq')

    def create(self, validated_data):
        acq_data = validated_data.pop('acq')
        acq = Acquisitions.objects.get_or_create(**acq_data)
        RawDatas.objects.create(acq=acq[0], **validated_data)
        return rawdatas

我的问题是,使用这个,如果我的Acquisitions实例已经存在,我会得到一个non_field_errors或另一个约束验证错误。

我想知道处理这个问题的正确方法是什么?

所以我可以使用嵌套的序列化器自动创建它,当我只想要信息(例如GET请求)时,我可以拥有我需要的所有字段(两个模型的每个字段)。

在此先感谢您的帮助 !

python django django-models django-serializer serializer
1个回答
0
投票

试试这个:

class AcquisitionSerializer(serializers.ModelSerializer):
    class Meta:
        model = Acquisitions
        fields = ('id', 'implant', 'beg_acq', 'duration_acq')

class RawDatasSerializer(serializers.ModelSerializer):
    class Meta:
        model = RawDatas
        fields = ('id', 'data_type', 'sampling_freq', 'bin_file', 'acq')

    def create(self, validated_data):
        acq_data = validated_data.pop('acq')
        acq = Acquisitions.objects.filter(id=acq_data.get('id')).first()

        if not acq:
            acq = AcquisitionSerializer.create(AcquisitionSerializer(), **acq_data)

        rawdata = RawDatas.objects.create(acq=acq, **validated_data)

        return rawdata

推荐问答