如何订购Django Rest Framework ManyToMany相关领域?

问题描述 投票:7回答:3

我有一个Django Rest Framework应用程序,其中包含以下(简化)models.py

class Photo(models.Model):
    ...

class Album(models.Model):
    ...
    photos = models.ManyToManyField(Photo, through='PhotoInAlbum', related_name='albums')

class PhotoInAlbum(models.Model):

    photo = models.ForeignKey(Photo)
    album = models.ForeignKey(Album)

    order = models.IntegerField()

    class Meta:
        ordering = ['album', 'order']

在我的serializers.py中,我有以下内容:

class AlbumSerializer(serializers.ModelSerializer):

    ...
    photos = serializers.PrimaryKeyRelatedField('photos', many=True)

我的问题是,我怎么能让AlbumSerializer返回由order字段订购的照片?

django many-to-many django-rest-framework
3个回答
5
投票

看起来处理ManyToManyFields关系的RelatedManager不遵循直通模型的排序。

由于您无法轻松地将序列参数添加到序列化程序字段,因此实现排序的最简单方法是使用序列化程序方法:

class AlbumSerializer(serializers.modelSerializer):
    # ...

    photos = serializers.SerializerMethodField('get_photos_list')

    def get_photos_list(self, instance):
        return PhotoInAlbum.objects\
            .filter(album_id=instance.id)\
            .order_by('order')\
            .values_list('photo_id', flat=True)

5
投票

自定义查询集的最佳解决方案是使用serializers.SerializerMethodField,但shezi的回复并不完全正确。你需要从serializer.data返回SerializerMethodField。所以解决方案应该是这样的:

class PhotoInAlbumSerializer(serialisers.ModelSerializer):
    class Meta:
        model = PhotoInAlbum


class AlbumSerializer(serializers.ModelSerializer):
    # ...

    photos = serializers.SerializerMethodField('get_photos_list')

    def get_photos_list(self, instance):
        photos = PhotoInAlbum.objects\
            .filter(album_id=instance.id)\
            .order_by('order')\
            .values_list('photo_id', flat=True)

        return PhotoInAlbumSerializer(photos, many=True, context=self.context).data

2
投票

通常,最简单的方法是在AlbumViewAlbumViewSet中执行此操作。您可以通过filtering执行此操作 - 在这种情况下,您应该在get_queryset中定义AlbumViewSet方法。

无论如何,只要您只获取数据,这是一个很好的解决方案。如果您希望POST和PUT方法与订购照片一起使用,您可以通过两种方式完成:

  • ManyToMany关系保持一致 - 修补create中的AlbumViewSet方法和__create_items中的restore_objectAlbumSerializer方法

要么

请注意,第二个解决方案不会混淆AlbumViewSet(甚至AlbumSerializer!) - 排序逻辑保留在关系字段代码中。

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