首页 > 解决方案 > 如何在模型 Y 中序列化模型 X 的外键,其中模型 X 与模型 Y 有关系?

问题描述

我需要在我的注册视图中序列化我的合同视图。

如果注册模型中有与合同模型相关的外键,我知道该怎么做,但在这种情况下,合同模型与注册模型之间存在关系。

我需要在一个更大的项目中这样做,这只是一个简单的样板。基本上,我希望我的输出是这样的:

[
    {
        "id": 1,
        "client": "John Doe",
        "contract": {
            "id": 1,
            "client": "John Doe",
            "name": "New Identity",
            "registration": 1
        }
    },
    {
        "id": 2,
        "client": "Jane Doe",
        "contract": {
            "id": 2,
            "client": "Jane Doe",
            "name": "Identity theft",
            "registration": 2
        }
    }
]

楷模:

class Client(models.Model):
    name = models.CharField(max_length=250)
    address = models.CharField(max_length=250)
    email = models.EmailField()

class Registration(models.Model):
    client = models.ForeignKey(Client, on_delete=models.CASCADE)

class Contract(models.Model):
    name = models.CharField(max_length=150)
    client = models.ForeignKey(Client, on_delete=models.CASCADE)
    registration = models.ForeignKey(Registration, on_delete=models.CASCADE)

视图集:

class ClientViewSet(viewsets.ModelViewSet):
    queryset = Client.objects.all()
    serializer_class = ClientSerializer


class RegistrationViewSet(viewsets.ModelViewSet):
    queryset = Registration.objects.all()
    queryset = queryset.select_related("client")
    serializer_class = RegistrationSerializer


class ContractViewSet(viewsets.ModelViewSet):
    queryset = Contract.objects.all()
    queryset = queryset.select_related("registration").prefetch_related(
        "client"
    )
    serializer_class = ContractSerializer

序列化器:

class ClientSerializer(serializers.ModelSerializer):
    class Meta:
        model = Client
        fields = "__all__"


class ContractSerializer(serializers.ModelSerializer):
    client = NameSerializer()

    class Meta:
        model = Contract
        fields = "__all__"


class RegistrationSerializer(serializers.ModelSerializer):
    client = NameSerializer()

    class Meta:
        model = Registration
        fields = "__all__"

标签: djangodjango-modelsdjango-rest-framework

解决方案


您仍然可以使用以下方式查询合约:register_obj.contract_set.all()这将返回所有外键指向 selected 的行register_obj

你的序列化器应该是这样的:

class RegistrationSerializer(serializers.ModelSerializer):
    client = NameSerializer()
    contracts = SerializerMethodField()

    class Meta:
        model = Registration
        fields = "__all__"

    def get_contracts(self, obj):
        # if you need all the contracts in a list:
        return ContractSerializer(obj.contract_set.all(), many=True).data

        # or if you just need the first one:
        return ContractSerializer(obj.contract_set.first()).data
        # you can also filter the query

推荐阅读