我有一个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
字段订购的照片?
看起来处理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)
自定义查询集的最佳解决方案是使用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
通常,最简单的方法是在AlbumView
或AlbumViewSet
中执行此操作。您可以通过filtering执行此操作 - 在这种情况下,您应该在get_queryset
中定义AlbumViewSet
方法。
无论如何,只要您只获取数据,这是一个很好的解决方案。如果您希望POST和PUT方法与订购照片一起使用,您可以通过两种方式完成:
ManyToMany
关系保持一致 - 修补create
中的AlbumViewSet
方法和__create_items
中的restore_object
和AlbumSerializer
方法要么
请注意,第二个解决方案不会混淆AlbumViewSet
(甚至AlbumSerializer
!) - 排序逻辑保留在关系字段代码中。