序列化Django中多对多关系的特定字段列表

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

我想要的是拥有多对多关系中的特定字段的列表,而不是该字段所在的字典列表。

例如,使用以下代码,我得到如下所示的结果

# models.py

from django.db import models

class Bar(models.Model):
    title = models.CharField(max_length=255)

class Foo(models.Model):
    title = models.CharField(max_length=255)
    bars = models.ManyToManyField(Bar, related_name="foos")


# serializers.py

from rest_framework.serializers import ModelSerializer 
from .models import Bar, Foo

class BarSerializer(ModelSerializer):
    class Meta:
        model = Bar
        fields = ("title",)

class FooSerializer(ModelSerializer):
    bars = BarSerializer(many=True)

    class Meta:
        model = Foo
        fields = ("title", "bars")


# views.py

from rest_framework.generics import ListAPIView
from .serializers import FooSerializer
from .models import Foo

class FooAPIView(ListAPIView):
    queryset = Foo.objects.prefetch_related("bars")
    serializer_class = FooSerializer

结果:

[
    {
        "title": "foo 1",
        "bars": [
            { "title": "bar title 1" },
            { "title": "bar title 2" },
            { "title": "bar title 3" }
        ]
    },
    {
        "title": "foo 2",
        "bars": [
            { "title": "bar title 4" },
            { "title": "bar title 5" },
            { "title": "bar title 6" }
        ]
    },
    {
        "title": "foo 3",
        "bars": [
            { "title": "bar title 7" },
            { "title": "bar title 8" },
            { "title": "bar title 9" }
        ]
    }
]

但我想要的是

bars
字段的标题列表。

期望的结果:

[
  {
    "title": "foo 1",
    "bars": ["bar title 1", "bar title 2", "bar title 3"]
  },
  {
    "title": "foo 2",
    "bars": ["bar title 4", "bar title 5", "bar title 6"]
  },
  {
    "title": "foo 3",
    "bars": ["bar title 7", "bar title 8", "bar title 9"]
  }
]

有什么方法可以做到这一点而不必重写 Django 方法吗?

python django serialization django-rest-framework django-serializer
2个回答
2
投票

您可以使用 serializerMethod 字段来做到这一点

class FooSerializer(ModelSerializer):
    bars = serializers.SerializerMethodField()

    class Meta:
        model = Foo
        fields = ("title", "bars")

    def get_bars(self, instance):
        return instance.bars.values_list('title', flat=True)

0
投票

试试这个...

from rest_framework import serializers
from .models import *

class BarSerializer(serializers.ModelSerializer):
    class Meta:
        model = Bar
        fields = ("title",)

class FooSerializer(serializers.ModelSerializer):
    bars = serializers.SerializerMethodField(read_only= True)

    def get_bars(self,obj):
        bars = [i.title for i in obj.bars.all()]
        return bars

    class Meta:
        model = Foo
        fields = ("title", "bars")

注意 - 此解决方案将特定 Foos 的 Bars 附加到列表中,而不是命中查询

另一种解决方案

您可以在模型中创建@property并在像这样的序列化器中使用它......

模型.py

class Foo(models.Model):
    title = models.CharField(max_length=255)
    bars = models.ManyToManyField(Bar, related_name="foos")

    @property
    def get_bars(self):
        return [i.title for i in self.bars.all()]

序列化器.py

class FooSerializer(serializers.ModelSerializer):
    
    class Meta:
        model = Foo
        fields = ("title", "get_bars")

双向输出

© www.soinside.com 2019 - 2024. All rights reserved.