Django REST Framework无法像Django本身一样为您自动优化查询。您可以在许多地方找到技巧,包括Django文档。它已经提到的是Django的REST框架应该自动,虽然有与之相关的一些挑战。
这个问题是非常特定于您的情况的,您正在使用一个自定义项SerializerMethodField
,该自定义项要求返回的每个对象。由于您正在使用Friends.objects
管理器发出新请求,因此优化查询非常困难。
但是,您可以通过不创建新的查询集,而从其他位置获取好友计数来使问题更好。这将需要在Friendship
模型上创建向后关系,很可能是通过related_name
字段上的参数,因此您可以预取所有Friendship
对象。但这仅在需要完整对象而不仅仅是对象数量时才有用。
这将导致视图和序列化器类似于以下内容:
class Friendship(models.Model):
from_friend = models.ForeignKey(User, related_name="friends")
to_friend = models.ForeignKey(User)
class GetAllUsers(generics.ListAPIView):
...
def get_queryset(self):
return User.objects.all().prefetch_related("friends")
class GetAllUseRSSerializer(serializers.ModelSerializer):
...
def get_is_friend_already(self, obj):
request = self.context.get('request', None)
friends = set(friend.from_friend_id for friend in obj.friends)
if request.user != obj and request.user.id in friends:
return True
else:
return False
如果只需要计数对象(类似于使用queryset.count()
或queryset.exists()
),则可以在查询集中对行添加反向关系计数。这可以通过在您的get_queryset
方法中添加.annotate(friends_count=Count("friends"))
到末尾(如果为related_name
wasfriends
)来完成,这会将friends_count
每个对象的属性设置为好友数。
这将导致视图和序列化器类似于以下内容:
class Friendship(models.Model):
from_friend = models.ForeignKey(User, related_name="friends")
to_friend = models.ForeignKey(User)
class GetAllUsers(generics.ListAPIView):
...
def get_queryset(self):
from django.db.models import Count
return User.objects.all().annotate(friends_count=Count("friends"))
class GetAllUseRSSerializer(serializers.ModelSerializer):
...
def get_is_friend_already(self, obj):
request = self.context.get('request', None)
if request.user != obj and obj.friends_count > 0:
return True
else:
return False