Home > Blockchain >  Getting data from another Foreign key - DRF
Getting data from another Foreign key - DRF

Time:12-22

The relations of tables are shown in the picture below. enter image description here

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')
  • Related