Saraswan Sinha
Saraswan Sinha

Reputation: 87

Accessing the data of a Parent model from a sub Model using the foreign key in Django

I am quite new to API and Django, please pardon me, if this is a silly question, but I cannot seem to get my head around it.

I have 2 models (ProductOrder and Product). The ProductOrder model has a foreign key from Product.

Here are the 2 models.


class Product(models.Model):
    name = models.CharField(max_length = 100)
    price = models.IntegerField(default = 1)
    

    def __str__(self) -> str:
        return f'{self.name} Price => {self.price}'


class ProductOrder(models.Model):
    product_id = models.ForeignKey(Product, on_delete=models.CASCADE)
    order_dis = models.FloatField()
    price = ** Need to get the price of the product using the product id **
    order_date = models.DateField()
    dis_price = price - order_dis
    

    def __str__(self) -> str:
        return f'{self.order_date} {self.dis_price}'

I intend to create an API and I wish to enter only the product_id and want to access the product price which would thereby aid in calc. some other fields. Is that possible?

Upvotes: 0

Views: 317

Answers (1)

Dan Yishai
Dan Yishai

Reputation: 782

This is usually done using a calculation when querying the data.

You should ask yourself the question "Do I store this data on the database, or do I calculate it based on the data in the database?". In this case probably the second one is the correct.

This can be done using QuerySet Annotate.

For the example, lets create some objects:

product = Product.objects.create(name="bagel", price=1)
ProductOrder.objects.create(product=product, order_dis=2.5)

And now lets query for that order

order = ProductOrder.objects.annotate(
    price=F("product__price"), 
    dis_price=F("product__price") - F("order_dis"),
).first()

print(order.price) # 1
print(order.dis_price) # 1.5

You can also implement it in Python to get the value for a single object:

class ProductOrder(models.Model):
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    order_dis = models.FloatField()
    order_date = models.DateField(auto_now=True)

    def get_dis_price(self) -> float:
        return self.product.price - self.order_dis

    def __str__(self) -> str:
        return f'{self.order_date} {self.dis_price}'

Then you will also be able to do

order.get_dis_price() # 1.5

Upvotes: 1

Related Questions