Возврат данных из поля модели в виде списка словарей

Рейтинг: 1Ответов: 1Опубликовано: 19.05.2023

Пишу диплом... Вообщем есть фронт который ждет по API данные в определенном формате. Конкретно поле Images модели Product фронт ждет вот в таком виде: введите сюда описание изображения

У меня пока получается просто словарь:

"images": {
    "src": "/media/pictures/toshiba_bbeea483ddb65e43a2c74c39ad7e96a7.png",
    "alt": "2"
},

Вот модели:

class ProductImage(models.Model):
    src = models.ImageField(
        upload_to='pictures',
        default='pictures/1.PNG',
        verbose_name="Ссылка",
        null=True,
    )
    alt = models.CharField(max_length=128, verbose_name="Описание")

class Product(models.Model):
    images = models.ForeignKey(
        ProductImage,
        on_delete=models.CASCADE,
        related_name="images",
        verbose_name="Фото продукта",
        null=True,
    )

И сериализаторы:

class ProductImageSerializer(serializers.ModelSerializer):
    src = serializers.SerializerMethodField()

    class Meta:
        model = ProductImage
        fields = ['src', 'alt']

    def get_src(self, obj):
        return obj.src.url

class ProductSerializer(serializers.ModelSerializer):
    images = ProductImageSerializer()
    class Meta:
        model = Product
        fields = '__all__'

На этом у меня идеи закончились, подскажите пожалуйста как привести данные в нужный формат?

Ответы

▲ 1

Немного поправил модели:

  • Если ты хочешь привязать картинки в модели Product, то нужно использовать ManyToMany
  • Иначе привязываешь в модели ProductImage - поле product, по ManyToOne

models

class Product(models.Model):
    name = models.CharField(max_length=128, verbose_name="Название")

class ProductImage(models.Model):
    src = models.ImageField(
        upload_to='pictures',
        default='pictures/1.PNG',
        verbose_name="Ссылка",
        null=True,
    )
    alt = models.CharField(max_length=128, verbose_name="Описание")
    product = models.ForeignKey(
        Product,
        on_delete=models.CASCADE,
    )

Для того, что бы вывести список объектов можно воспользоваться ListSerializer

serializers

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = '__all__'

class ProductImageSerializer(serializers.ModelSerializer):
    src = serializers.SerializerMethodField()
    product = ProductSerializer()

    class Meta:
        model = ProductImage
        fields = ['src', 'alt', 'product']

    def get_src(self, obj):
        return obj.src.url

class ProductListSerializer(serializers.ListSerializer):
    child = ProductImageSerializer()

Достаем id необходимого продукта из запроса, фильтруем объекты ProductImage, создаем список этих объектов и передаем их в сериализатор ProductListSerializer

views

class ProductViewSet(ModelViewSet):
    queryset = ProductImage.objects.all()
    serializer_class = ProductListSerializer

    @action(
        detail=False,
        methods=('GET',),
        url_path='product/(?P<id>\d+)',)
    def get_product_images(self, request, id):
        queryset = ProductImage.objects.filter(product=id)
        queryset = [obj for obj in queryset]
        serializer = ProductListSerializer(queryset)
        return Response({'images': serializer.data})

Создал две картинки для объекта My_product, вывод:

{
    "images": [
        {
            "src": "/pictures/1a22513a-f19e-4338-b241-14a37d53c39d_1655656234.9439957_mpbL6b8.jpeg",
            "alt": "first_image",
            "product": {
                "id": 1,
                "name": "My_product"
            }
        },
        {
            "src": "/pictures/1adsa13a-f23e-2138-b31211-14a37d5dsad_165121asad34.9439957_mpbL6b8.jpeg",
            "alt": "second_image",
            "product": {
                "id": 1,
                "name": "My_product"
            }
        }
    ]
}