Django Rest Framework - 自动注释查询集
Posted
技术标签:
【中文标题】Django Rest Framework - 自动注释查询集【英文标题】:Django Rest Framework - automatically annotate queryset 【发布时间】:2018-06-17 15:01:31 【问题描述】:我在项目的许多不同地方都使用了一个Serializer
。我需要使用一个注释,但问题是我不想在所有视图中都对其进行注释,所以我想在 Serializer
本身中进行通用注释。
有可能吗?
现在我需要在每次序列化之前这样做:
City.objects....filter....annotate(
number_of_users_here_now=Count('current_userprofiles'))
我试过了:
class NumberOfUsersInCityNowField(serializers.Field):
def to_native(self, value):
count = value.annotate(
number_of_users_here_now=Count('current_userprofiles'))['current_userprofiles__count']
return count
class CityMapSerializer(serializers.ModelSerializer):
number_of_users_here_now = NumberOfUsersInCityNowField()
class Meta:
model = City
fields = ('place_id', 'lat', 'lng', 'number_of_users_here_now', 'formatted_address')
这个Serializer
返回:
/api/ajax-check-trip-creation 处的 AttributeError 得到 AttributeError 尝试获取字段
number_of_users_here_now
的值时 序列化程序CityMapSerializer
。序列化器字段可能被命名 不正确且不匹配City
实例上的任何属性或键。 原始异常文本是:“城市”对象没有属性 'number_of_users_here_now'。
编辑
class NumberOfUsersInCityNowField(serializers.PrimaryKeyRelatedField):
def get_queryset(self):
return City.objects.annotate(
number_of_users_here_now=Count('current_userprofiles'))
class CityMapSerializer(serializers.ModelSerializer):
# number_of_users_here_now = serializers.IntegerField()
number_of_users_here_now = NumberOfUsersInCityNowField()
class Meta:
model = City
fields = ('place_id', 'lat', 'lng', 'number_of_users_here_now', 'formatted_address')
但是
serializers.CityMapSerializer(City.objects.all()[:3],many=True).data
仍然返回:
AttributeError: 'City' object has no attribute 'number_of_users_here_now'
【问题讨论】:
你在模型中有相同的字段名吗? 不,这不是原生字段。我需要为每个城市添加用户配置文件的数量。 【参考方案1】:您可以将查询集的count
方法与SerializerMethodField
一起使用:
class CityMapSerializer(serializers.ModelSerializer):
number_of_users_here_now = SerializerMethodField()
def get_number_of_users_here_now (self, obj):
return obj.current_userprofiles.count()
UPD
为了避免 n+1 查询,您可以尝试实现NumberOfUsersInCityNowField
序列化程序的get_queryset
方法:
class NumberOfUsersInCityNowField(serializers.PrimaryKeyRelatedField):
def get_queryset(self):
return City.objects.annotate(
number_of_users_here_now=Count('current_userprofiles'))['current_userprofiles__count']
【讨论】:
我不想避免这样做,因为它访问每个城市的数据库,而不是像注释那样只访问一次。 @MilanoSlesarik 是的,你是对的,尝试从PrimaryKeyRelatedField
继承并覆盖 get_queryset
方法。
您的解决方案似乎是我想要的,但不幸的是它返回了相同的错误。我已经在问题的底部添加了代码。
城市是模型 UserProfile 中的外键,related_name='current_userprofiles'
@MilanoSlesarik 抱歉,无法为您提供更好的建议。如果您找不到解决方案,您可能应该尝试实现注释的 mixin 类并将其添加到您的所有视图中。以上是关于Django Rest Framework - 自动注释查询集的主要内容,如果未能解决你的问题,请参考以下文章
Django rest framework 之 DictField、ListField、自定义字段
python 使用Django Rest Framework在Django中自定义用户实现
django-rest-framework 自定义视图集检索多个查找参数