考虑以下三个模型:

class Genre(models.Model):
    slug = models.CharField(max_length=30, unique=True)
    name = models.CharField(max_length=300)

class Group(models.Model):
    slug = models.CharField(max_length=30, unique=True)
    name = models.CharField(max_length=300)
    genre = models.ForeignKey('Genre', related_name='groups')

class Album(models.Model):
    name = models.CharField(max_length=300)
    track_count = models.IntegerField()
    artist = models.ForeignKey('Group', related_name='albums')


现在,我需要这种DRF输出:

[
  {'name': 'Rock', 'albums': [
         {'name': 'Meteora', 'track_count': 12},
         {'name': 'Master of Puppets', 'track_count': 10'}]
  },
  {..},
]


换句话说,我需要绕过“组”模型来获取每种流派的所有专辑。我已经通过这种方式实现了类似的目的:

views.py

class SegmentViewSet(viewsets.ModelViewSet):

    queryset = Genre.objects.all().annotate(Count('name'))
    serializer_class = GenreSerializer


serializers.py

class GroupSerializer(serializers.ModelSerializer):
    albums = AlbumSerializer(many=True, read_only=True)

    def to_representation(self, value):
        return value.products.annotate(Count('id')).values('name', 'sap_code')

class Meta:
    model = Group
    fields = ('albums',)


class GenreSerializer(serializers.ModelSerializer):
    albums = GroupSerializer(many=True, read_only=True)

    class Meta:
        model = Genre
        fields = ('id',
                  'name',
                  'albums')


这给了我这样的东西:

[
  {'name': 'Rock', 'albums': [
      [
        {'name': 'Meteora', 'track_count': 12},
        {...},
        {...}
      ],
      [
        {...},
        {...}
      ]
    ]
  }
]


这是专辑,按专辑分组,按流派分组。那是一个嵌套数组,我只需要将按流派分组的专辑放在一个数组中。

我知道我使用to_representation函数的解决方案非常脏,但这与我要寻找的类似。但是,这就是自定义相关字段的用途。

是否可以在不将专辑直接链接到流派的情况下获得所需的输出?确实有这样的理由保留事情。

我已经尝试过与自定义相关的字段PrimaryKeyRelatedField,甚至试图在我的视图中重载get_queryset。我有什么事吗

最佳答案

您可以尝试如下定义序列化器:

from rest_framework import serializers


class GenreSerializer(serializers.ModelSerializer):
    albums = serializers.SerializerMethodField()

    class Meta:
        model = Genre

    def get_albums(self, obj):
        albums = Album.objects.filter(group__genre=obj)
        albums_serializer = AlbumSerializer(data=albums, many=True)
        albums_serializer.is_valid()
        return albums_serializer.data


class AlbumSerializer(serializers.ModelSerializer):
    class Meta:
        model = Album


结果应如下所示:

[{
        'name': 'Rock',
        'albums': [{
                'name': 'Meteora',
                'track_count': 13
            },
            {
                'name': 'Master of Puppets',
                'track_count': 12
            },
            {
                'name': 'Nevermind',
                'track_count': 11
            }
        ]
    },
    {
        'name': 'Pop',
        'albums': [{
                'name': 'Ray of Light',
                'track_count': 11
            },
            {
                'name': 'Thriller',
                'track_count': 14
            }
        ]
    }
]


请注意,这是未经高度优化和未经测试的,但是从这里开始,我确定您知道如何在视图中使用GenreSeralizer和优化代码。

08-18 00:30