在Django Rest Framework中,如何限制使用RelatedField Serializer关系获取的字段?

时间:2018-04-13 13:29:42

标签: django django-rest-framework

以序列化程序from the DRF docs为例:

class AlbumSerializer(serializers.ModelSerializer):

    tracks = serializers.HyperlinkedRelatedField(
        many=True,
        read_only=True,
        view_name='track-detail'
    )

    class Meta:
        model = Album
        fields = ('album_name', 'artist', 'tracks')

当DRF执行查询以获取特定track的所有album时,生成的SQL会选择每个track列的 all 。如何将其限制为仅请求特定列,例如将用于响应中每个轨道的超链接的pk

(为什么?因为可能会有一个很多的曲目返回,并且每个曲目在数据库的行中都有 lot ,这可能是很多返回了不必要的数据。)

2 个答案:

答案 0 :(得分:0)

您可以使用SerializerMethodField自行构建查询集并使用value_list

class AlbumSerializer(serializers.ModelSerializer):

    tracks = serializers.SerializerMethodField()

    def get_tracks(self, instance):
        return TracK.objects.filter(album=self).values_list('id', flat=True)


    class Meta:
        model = Album
        fields = ('album_name', 'artist', 'tracks')

答案 1 :(得分:0)

我认为这样做......

from rest_framework import serializers
from rest_framework.reverse import reverse

from myapp.models import Album


class AlbumSerializer(serializers.ModelSerializer):

    tracks = serializers.SerializerMethodField()

    class Meta:
        model = Album
        fields = ('album_name', 'artist', 'tracks')

    def get_tracks(self, instance):
        "Returns a list of URLs for Tracks' API detail views"

        request = self.context.get('request')

        tracks = []

        for track in instance.tracks.values('pk'):
            tracks.append(reverse(
                                'track-detail',
                                kwargs={'pk': track['pk']},
                                request=request
                            ))

        return tracks

我们手动创建HyperlinkedRelatedField()的结果(将曲目列表返回到曲目的API详细信息页面),但使用查询集中的values()限制从数据库中提取的数据。< / p>

这假定track-detail网址格式的参数为pk

更换PrimaryKeyRelatedField()甚至更简单。将上面的get_tracks()方法替换为:

    def get_tracks(self, instance):
        "Returns a list of Track IDs"
        return instance.tracks.values_list('pk', flat=True)

感谢@jmny指导我使用SerializerMethodField()