Я пытаюсь просмотреть вложенные аннотатные (агрегированные/вычисленные) поля в сериализаторах Django REST Framework. Это позволит работать более чисто с аннотированными полями. Это сообщение похоже на Aggregate (and other annotated) fields in Django Rest Framework serializers, но я хотел бы, чтобы подобный метод работал вложенным. Ниже методология видна, как это работает без вложенности и как она, похоже, не работает с вложением.Вложенные аннотированные поля в Django REST Framework serializers
Я знаю, что это может быть достигнуто вручную (с помощью Django View) или с помощью методов, которые перегружают базу данных, которая мне не интересна. Но, возможно, для этой проблемы есть эффективное и элегантное решение.
следующих работ (не вложенных друг в друга)
Модели
class IceCreamCompany(models.Model):
name = models.CharField(max_length=255)
class IceCreamTruck(models.Model):
company = models.ForeignKey('IceCreamCompany', related_name='trucks')
capacity = models.IntegerField()
class IceCreamTruckDriver(models.Model):
name = models.CharField(max_length=255)
first_name = models.CharField(max_length=255)
truck = models.ForeignKey('IceCreamTruck', related_name='drivers')
сериализаторы
class IceCreamTruckDriverSerializer(serializers.ModelSerializer):
class Meta:
model = IceCreamTruckDriver
fields = ('name', 'first_name')
class IceCreamTruckSerializer(serializers.ModelSerializer):
drivers = IceCreamTruckDriverSerializer(many=True, read_only=True)
class Meta:
model = IceCreamTruck
fields = ('capacity', 'drivers')
class IceCreamCompanySerializer(serializers.ModelSerializer):
trucks = IceCreamTruckSerializer(many=True, read_only=True)
amount_of_trucks = serializers.IntegerField()
class Meta:
model = IceCreamCompany
fields = ('name', 'trucks', 'amount_of_trucks')
Viewset
class IceCreamCompanyViewSet(viewsets.ModelViewSet):
queryset = IceCreamCompany.objects.prefetch_related('trucks', 'trucks__drivers')\
.annotate(amount_of_trucks=Count('trucks'))\
.all()
serializer_class = IceCreamCompanySerializer
Результат
"results": [
{
"name": "Pete Ice Cream",
"trucks": [
{
"capacity": 35,
"drivers": [
{
"name": "Damian",
"first_name": "Ashley"
},
{
"name": "Wilfrid",
"first_name": "Lesley"
}
]
},
{
"capacity": 30,
"drivers": [
{
"name": "Stevens",
"first_name": "Joseph"
}
]
},
{
"capacity": 30,
"drivers": []
}
],
"amount_of_trucks": 3
}
]
Следующая не работает (вложенными)
Одинаковые модели
сериализаторы
class IceCreamTruckDriverSerializer(serializers.ModelSerializer):
class Meta:
model = IceCreamTruckDriver
fields = ('name', 'first_name')
class IceCreamTruckSerializer(serializers.ModelSerializer):
drivers = IceCreamTruckDriverSerializer(many=True, read_only=True)
amount_of_drivers = serializers.IntegerField()
class Meta:
model = IceCreamTruck
fields = ('capacity', 'drivers', 'amount_of_drivers')
class IceCreamCompanySerializer(serializers.ModelSerializer):
trucks = IceCreamTruckSerializer(many=True, read_only=True)
class Meta:
model = IceCreamCompany
fields = ('name', 'trucks')
Viewset
class IceCreamCompanyViewSet(viewsets.ModelViewSet):
queryset = IceCreamCompany.objects.prefetch_related('trucks', 'trucks__drivers')\
.annotate(trucks__amount_of_drivers=Count('trucks__drivers'))\
.all()
serializer_class = IceCreamCompanySerializer
Результат
AttributeError at /ice/
Got AttributeError when attempting to get a value for field `amount_of_drivers` on serializer `IceCreamTruckSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `IceCreamTruck` instance.
Original exception text was: 'IceCreamTruck' object has no attribute 'amount_of_drivers'.
Разве вы не должны указывать поле типа amount_of_drivers вместо truck__amount_of_drivers? – Roba
Если я использую amount_of_drivers в функции аннотаций в наборе запросов, он пытается найти поле amount_of_drivers в IceCreamCompanySerializer, которое не будет вложенным аннотированным полем. Я хочу, чтобы это было возможно внутри IceCreamTruckSerializer. – Robin
Нет, сэр, я предлагаю переименовать аннотацию: .annotate (amount_of_drivers = Count ('trucks__drivers')); ошибка называет эту проблему, тот факт, что имя аннотированного столбца не было найдено в наборе запросов. Имя аннотированного столбца - просто имя, не пересекающее отношения для вас. – Roba