【问题标题】:Django Rest Framework - automatically annotate querysetDjango Rest Framework - 自动注释查询集
【发布时间】: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'

【问题讨论】:

  • 你在模型中有相同的字段名吗?
  • 不,这不是原生字段。我需要为每个城市添加用户配置文件的数量。

标签: python django serialization django-rest-framework django-orm


【解决方案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 类并将其添加到您的所有视图中。
猜你喜欢
  • 2021-04-23
  • 2013-08-28
  • 1970-01-01
  • 1970-01-01
  • 2016-09-30
  • 2018-10-26
  • 2020-09-25
  • 2020-05-14
  • 1970-01-01
相关资源
最近更新 更多