The relations of tables are shown in the picture below.
I have a main Table named Product
. Two tables ProductImage
and OrderedProduct
have a Foreign key set to them.
I want to retrieve the image from OrderedProduct
. How should I write the code for Serialization for it?
Thanks
This is my model.py file:
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 = ('product', 'quantity',
'product_name', 'product_price', 'product_img')
I've read the documentation, and asked in some programming groups but couldn't find any good solution. I am expecting someone to give a reference that leads to the solution.
CodePudding user response:
Solution 1
You can use the SerializerMethodField like that:
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))
output:
[
{
"product": 1,
"quantity": 100,
"product_name": "ProductX",
"product_price": 123,
"product_imgs": ["url1", "url2"]
}
]
Solution 2
If you dont have a structure contraint i propose you to change this structure and create a serializer for each model and on order retrieve you send product object like that:
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')
output:
[
{
"product": {
"name": "productX",
"price": 100,
"product_images": [
{
"image": "some_url"
},
{
"image": "some_url2"
}
]
},
"quantity": 123
}
]
CodePudding user response:
How about this?
class Product(models.Model):
name = models.CharField(max_length=50)
description = models.TextField()
price = models.FloatField()
images = models.ManyToManyField(ProductImage) # you can select multiple images from here
def __str__(self) -> str:
return self.name
class ProductImage(models.Model):
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 ImageSerializer(serializers.ModelSerializer):
class Meta:
model = ProductImage
fields ["image"]
class OrderedProductSerializer(serializers.ModelSerializer):
product_name = serializers.CharField(source='product.name')
product_price = serializers.FloatField(source='product.price')
product_img = serializer.ImageSerializer(source='product.image',many=true, read_only=True)
class Meta:
model = OrderedProduct
fields = ('product', 'quantity',
'product_name', 'product_price', 'product_img')