首页 > 解决方案 > 使用外键的嵌套序列化程序,DRF 中只有一个对象

问题描述

我正在使用带有两个模型的 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 ,我已经理解这意味着它是不允许的,因为一对多的反向意味着它需要具有获取多个对象的能力。

谢谢

标签: djangodjango-rest-framework

解决方案


I would suggest for you to use two different fields for this.

Something like this:

class ServiceSerializer(serializers.ModelSerializer):

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

So, for input - you will have only write_only attribute which won't be serialized on the way out - only when you post ( you can decide with required attribute to make it optional )

And vice versa for messages - only read only.

And you handle it accordingly in create method.


推荐阅读