简体   繁体   English

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

[英]In Django Rest Framework, how to restrict fields fetched with a RelatedField Serializer relation?

Taking this example of a Serializer from the DRF docs : DRF文档中的序列化器为例:

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')

When DRF does the query to fetch all the track s for a particular album , the SQL generated selects all of each track 's columns. 当DRF执行查询以获取特定album所有track ,生成的SQL会选择每个track所有列。 How would I restrict it to only request specific columns, eg the pk that would be used for the Hyperlinks to each track in the response? 我如何将其限制为仅请求特定列,例如用于超链接的pk到响应中的每个轨道?

(Why? Because there might be a lot of tracks returned and each one have a lot of data in its row in the database, which could be a lot of unnecessary data returned.) (为什么?因为可能会返回很多轨道,并且每个轨道在数据库的行中都有很多数据,所以可能会返回很多不必要的数据。)

You can use SerializerMethodField to build yourself the queryset and use value_list . 您可以使用SerializerMethodField来构建自己的queryset并使用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')

I think this does it... 我认为这可以做到...

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

We're manually creating the result of a HyperlinkedRelatedField() (returning a list of URLs to the track's API detail pages), but restricting the data fetched from the database using values() in the queryset. 我们正在手动创建HyperlinkedRelatedField()的结果(将URL列表返回到轨道的API详细信息页面),但是使用queryset中的values()限制了从数据库中获取的数据。

This assumes that the track-detail URL pattern has a parameter of pk . 假设track-detail URL模式的参数为pk

Replacing a PrimaryKeyRelatedField() is even simpler. 替换PrimaryKeyRelatedField()甚至更简单。 Replace the get_tracks() method above with this: 替换上面的get_tracks()方法:

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

Thanks to @jmny for heading me towards using SerializerMethodField() . 感谢@jmny引导我使用SerializerMethodField()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM