Taking this example of a Serializer 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')
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. 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?
(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 .
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.
This assumes that the track-detail
URL pattern has a parameter of pk
.
Replacing a PrimaryKeyRelatedField()
is even simpler. Replace the get_tracks()
method above with this:
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()
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.