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

时间:2014-08-05 08:11:33

标签: django many-to-many django-rest-framework

我有一个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订购的照片?

3 个答案:

答案 0 :(得分: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)

答案 1 :(得分: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 :(得分:2)

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

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

  • 保持ManyToMany关系 - 修补create中的AlbumViewSet方法以及__create_items中的restore_objectAlbumSerializer方法}}

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