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.
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
}
]
I suggest you move the product's image to the product model. Think about it, the image of a product is a product's attribute. This will fix your problem and clean up your code.
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()
So now you can access it using source='product.image
On another note: I noticed you added some fields in your serial OrderedProductSerializer
but they are not in your OrderedProduct
model. That is likely to give you an error.
So I recommend you spend some more time polishing up your models.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.