sourceを使用する
sourceを使用することで、Metaに指定したモデルに関連する値を抜き出すことが出来ます。
使い方としては以下のような感じです。
models.py
class Pref(models.Model):
    name = models.CharField(...)
    point = models.PointField(geography=True...)
    def get_lat(self):
        return self.point.y
    def get_long(self):
        return self.point.x
    ...
class City(models.Model):
    city = models.ForeignKey(Pref, related_name='cities')
    name = models.CharField(...)
    ...
serializers.py
class PrefSerializer(serializers.ModelSerializer):
    city_count =  serializers.IntegerField(source='cities.count', read_only=True)
    class Meta:
        model = Pref
        fields = ('id', 'name', 'city_count')
このようにrelated_nameを付けた名称からcountを取ったり、上記のモデルからであればget_latやget_longを指定することも出来ます。
SerializerMethodFieldを使用する
SerializerMethodFieldを使用すると、serializerの中でfield名に沿った独自の関数を作成することが出来ます。
使い方としては以下のような感じです。get_ + field名で関数を作るところが特徴的です。
serializers.py
class PrefSerializer(serializers.ModelSerializer):
    is_pickup =  serializers. SerializerMethodField(read_only=True)
    class Meta:
        model = Pref
        fields = ('id', 'name', 'is_pickup')
    def get_is_pickup(self, instance):
        return instance.pickup_start <= timezone.now() < instance.pickup_end
上記のもの程度であれば、モデル内に関数を用意してsourceを使ってしまっても良いですが、ちょっとした判定などを行うのに使うと便利です。
ただし、自由度が非常に高いあまりに、この中で複雑な処理を書くことはパフォーマンスの観点から避けた方が良いと思います。
to_representationを使用する
to_representation関数をoverrideすることで、view側のquerysetでannotateなどで生成した変数名を使いたい時や、データの階層を変えたい時などに使うことが出来ます。
views.py
class PrefList(mixins.ListModelMixin, generics.GenericAPIView):
    permission_classes = (AllowAny,)
    serializer_class = PrefSerializer
    queryset = Pref.objects.annotate(
                rank=Window(
                    expression=Rank(),
                    order_by=F('population').desc()
                )
            )
serializers.py
class PrefSerializer(serializers.ModelSerializer):
    class Meta:
        model = Pref
        fields = ('id', 'name')
    def to_representation(self, instance):
        ret = super(PrefSerializer, self).to_representation(instance)
        ret['rank'] = instance.rank
        return ret
上記の例では、views側で生成したrankをto_representationで入れています。fieldsに入れようとすると、そのようなfieldは無いとエラーが出てしまいます。










モデル内に存在しないfieldを返す方法をいくつか上げてみました。
ただし、どの方法も注意しないといけないのは、querysetでrelationなどを良く考えながらselect_relatedやprefetch_relatedなどを加えてパフォーマンスを保つことには気を付けましょう。