Сериализатор фреймворка Django Rest не хочет принимать возвращенный список и возвращает объект AttributeError ‘str’, не имеющий атрибута ‘x’

#python #django #django-rest-framework #django-serializer

#python #django #django-rest-framework #django-serializer

Вопрос:

Итак, я пытаюсь объединить список цветов и вернуть набор запросов сериализатору, однако serialzier, похоже, по какой-то причине не принимает это.

При запуске команд в оболочке я получаю:

 >>> from django.contrib.postgres.aggregates import ArrayAgg
>>> from inventory.models import Product
>>> products = Product.objects.filter(category__parent__name__iexact='fliser').distinct().aggregate(colors_field=ArrayAgg('colors__name'))
>>> print(products)
{'colors_field': ['Beige', 'Grå', 'Hvit', 'Sort', 'Beige', 'Gul', 'Rød']}
  

Что является ожидаемым результатом.

Сериализатор структурирован следующим образом:

 class ProductFiltersByCategorySerializer(serializers.ModelSerializer):
    """
    A serializer to display available filters for a product lust 
    """

    colors = serializers.StringRelatedField(read_only=True, many=True)

    class Meta:
        model = Product
        fields = ['colors']
  

Набор представлений выглядит следующим образом:

 class ProductFiltersByCategory(generics.ListAPIView):
    """
    This viewset takes the category parameter from the url and returns related product filters
    """

    serializer_class = ProductFiltersByCategorySerializer

    def get_queryset(self):
        category = self.kwargs['category']
        queryset = Product.objects.filter(category__parent__name__iexact=category).distinct().aggregate(colors_field=ArrayAgg('colors__name'))
        return queryset
  

И соответствующая часть модели выглядит следующим образом:

 class Product(models.Model):

    ...
    colors = models.ManyToManyField(
        ProductColor,
        related_name='product_color'
    )
    ...
  

Ошибка при попытке доступа к конечной точке 'str' object has no attribute 'colors' .

Желаемого результата:

 [
    {
        "colors": [
            "Red",
            "Orange",
        ],
    },
]
  

Комментарии:

1. как вы передаете данные в сериализаторы? Покажите нам код.

2. @ArakkalAbu расширение ListAPIView обычно выполняет тяжелую работу, и указания serializer_class = ProductFiltersByCategorySerializer должно быть достаточно. Попытка выполнить serializer = ProductFiltersByCategorySerializer(queryset, many=True) return Response(serializer.data) в методе get_queryset возвращает ту же ошибку.

3. Ваш get_queryset() метод возвращает dict объект. Во-первых, это не должно быть dict вторым, это должен быть объект, подобный списку

4. Как бы я это сделал? Не могли бы вы привести мне пример? Я добавил желаемый результат в сообщение. Извините, совсем новичок в python / django.

Ответ №1:

Здесь вам не нужен ListAPIView класс, используйте APIView как

 from rest_framework.views import APIView
from rest_framework.response import Response


class MyAPIView(APIView):
    def get(self, request, *args, **kwargs):
        category = kwargs['category']
        agg_result = Product.objects.filter(
            category__parent__name__iexact=category
        ).distinct().aggregate(colors_field=ArrayAgg('colors__name'))
        return Response(agg_result)  

Комментарии:

1. Есть ли какой-нибудь способ удалить дублирующиеся поля? На данный момент, если значение зарегистрировано в обоих экземплярах, будут отображаться две одинаковые строки: { "result": [ "Beige", "Red", "Yellow", "Beige", "White", "Gray", "Black" ] } .

2. idk, лучше вам задать новый вопрос.

3. Выяснив это, вы можете просто добавить distinct=True в метод ArrayAgg. Спасибо за всю помощь.

Ответ №2:

 class ProductColorSerializer(serializers.ModelSerializer):
    class Meta:
        model = ProductColor
        fields = '__all__'

class ProductFiltersByCategorySerializer(serializers.ModelSerializer):
    """
    A serializer to display available filters for a product lust 
    """

    product_color = ProductColorSerializer(many=True)

    class Meta:
        model = Product
        fields = ['product_color']
  

Комментарии:

1. Я не думаю, что эта настройка сгенерирует требуемый результат

2. этого не произойдет, потому что сериализатор получает объект dict , а не QerySet