使用外键仅在DRF中使用一个对象的嵌套序列化器

时间:2018-07-24 13:17:32

标签: django django-rest-framework

我正在将Django Rest Framework与两个模型一起使用,即服务和消息,其中服务可以包含许多消息。使用外键。

class Service(models.Model):
    servicename = models.TextField(blank=False)
    sender = models.TextField(blank=False)


class Message(models.Model):

    service = models.ForeignKey(Service, related_name='messages', on_delete=models.CASCADE)
    description = models.TextField(blank=False)

唯一的用例是您输入服务的位置,该服务被嵌套以接受消息的输入。因此,服务将同时创建服务和消息。如果该服务不存在,它将被创建。如果确实存在,则该消息将指向该服务。

因为它是一对多的,所以我似乎需要在序列化器中使用many=True,这是不希望有的,因为从不存在同时输入两个消息的用例,这也意味着Web UI将不起作用,因为不支持列表。

class MessageSerializer(serializers.ModelSerializer):

    class Meta:
        model = Message
        fields = ('description',)


class ServiceSerializer(serializers.ModelSerializer):

    messages = MessageSerializer(many=True)

    class Meta:
        model = Service
        fields = ('servicename', 'sender', 'messages')

    def create(self, validated_data):
        messages_data = validated_data.pop('messages')
        print(messages_data)
        service, created = Service.objects.get_or_create(
            servicename=validated_data['servicename'],
            sender=validated_data['sender']
        )
        Message.objects.create(service=service, **messages_data[0])
        return service

那么,是否有可能在输入期间只有一个对象的嵌套序列化器?删除many = True会导致典型的AttributeError,我已经理解这意味着不允许这样做,因为一对多的反向操作意味着它需要具有处理多个对象的能力。

谢谢

1 个答案:

答案 0 :(得分:0)

我建议您为此使用两个不同的字段。

类似这样的东西:

class ServiceSerializer(serializers.ModelSerializer):

    messages = MessageSerializer(many=True, read_only=True)
    message = MessageSerializer(write_only=True)

因此,对于输入-您将只有write_only属性,不会在出局时进行序列化-仅在您发布时(您可以使用required属性来决定使其可选)

反之亦然-仅只读。

然后您可以在create方法中进行相应处理。