Получение данных из другого внешнего ключа - DRF
Отношения таблиц показаны на рисунке.
У меня есть основная таблица с именем Product
. Две таблицы ProductImage
, OrderedProduct
имеют установленный для них внешний ключ.
Теперь я хочу получить изображение из OrderedProduct
. Как я должен написать код для сериализации для этого?
Спасибо
Это мой model.py файл:
class Product(models.Model):
name = models.CharField(max_length=50)
description = models.TextField()
def __str__(self) -> str:
return self.name
class ProductImage(models.Model):
product = models.ForeignKey(
Product, on_delete=models.CASCADE, related_name='product_images')
image = models.ImageField(upload_to="images/", null=True, blank=True)
class OrderedProduct(models.Model):
product = models.ForeignKey(
Product, on_delete=models.CASCADE, related_name='ordered_products')
quantity = models.IntegerField()
Serializers.py
class OrderedProductSerializer(serializers.ModelSerializer):
product_name = serializers.CharField(source='product.name')
product_price = serializers.FloatField(source='product.price')
# product_img = >>> what should I do here? <<<
class Meta:
model = OrderedProduct
fields = ('user', 'product', 'quantity',
'delivered', 'product_name', 'product_price', 'product_img')
Я читал документацию, спрашивал в некоторых группах по программированию, но не смог найти никакого хорошего решения. Я ожидаю, что кто-нибудь даст ссылку, которая приведет к решению.
Я предлагаю вам переместить изображение продукта в модель продукта. Подумайте об этом, изображение товара - это атрибут товара. Это решит вашу проблему и очистит ваш код.
class Product(models.Model):
name = models.CharField(max_length=50)
description = models.TextField()
image = models.ImageField(upload_to="images/", null=True, blank=True) # new
def __str__(self) -> str:
return self.name
class OrderedProduct(models.Model):
product = models.ForeignKey(
Product, on_delete=models.CASCADE, related_name='ordered_products')
quantity = models.IntegerField()
Теперь вы можете получить доступ к нему, используя source='product.image
Еще одно замечание:
Я заметил, что вы добавили некоторые поля в вашей серийной OrderedProductSerializer
модели, но их нет в вашей OrderedProduct
модели. Это может привести к ошибке.
Поэтому я рекомендую вам потратить еще немного времени на полировку ваших моделей.
Решение 1
Вы можете использовать SerializerMethodField вот так:
class OrderedProductSerializer(serializers.ModelSerializer):
product_name = serializers.CharField(source='product.name')
product_price = serializers.FloatField(source='product.price')
product_imgs = serializers.SerializerMethodField()
class Meta:
model = OrderedProduct
fields = ('product', 'quantity',
'product_name', 'product_price', 'product_imgs')
def get_product_imgs(self, order):
return list(order.product.product_images.all().values_list('image', flat=True))
вывод:
[
{
"product": 1,
"quantity": 100,
"product_name": "ProductX",
"product_price": 123,
"product_imgs": ["url1", "url2"]
}
]
Решение 2
Если у вас нет ограничений по структуре, я предлагаю вам изменить эту структуру и создать сериализатор для каждой модели, а при получении заказа отправлять объект продукта следующим образом:
class ProductImagesSerializer(serializers.ModelSerializer):
class Meta:
model = ProductImage
fields = ('image',)
class ProductSerializer(serializers.ModelSerializer):
product_images = ProductImagesSerializer()
class Meta:
model = Product
fields = ('name', 'price', 'product_images')
class OrderedProductSerializer(serializers.ModelSerializer):
product = ProductSerializer()
class Meta:
model = OrderedProduct
fields = ('product', 'quantity')
вывод:
[
{
"product": {
"name": "productX",
"price": 100,
"product_images": [
{
"image": "some_url"
},
{
"image": "some_url2"
}
]
},
"quantity": 123
}
]