Sharpless512
Sharpless512

Reputation: 3222

Get model attribute from other class in same model

How do I get value of another class in the same model?
Can I also use properties? I want to use Finance.net_income and Finance.net_margin inside the Stats Class. I tried searching for an anwser but I couldnt find it, I am also new to django.

class Stats(models.Model):
    stock = models.ForeignKey(Stock, on_delete=models.CASCADE)
    shares_outstanding = models.FloatField(default=0)  

    @property
    def earnings_per_share(self):
        ####### ISSUE IS HERE #####
        return Finance.net_income / self.shares_outstanding

class Finance(models.Model):
    stock = models.ForeignKey(Stock, on_delete=models.CASCADE)
    total_revenue = models.FloatField(default=0) 
    operating_income = models.FloatField(default=0) 
    date = models.DateField(null=True, blank=True)
    net_income = models.FloatField(default=0) 
    cash = models.FloatField(default=0) 
    total_debt = models.FloatField(default=0) 

    @property
    def operating_margin(self):
        if self.total_revenue:
            now = (self.operating_income / self.total_revenue)*100
        else:
            now = 0
        return now

    @property
    def net_margin(self):
        if self.total_revenue:
            now = (self.net_income / self.total_revenue)*100
        else:
            now = 0
        return now

Upvotes: 2

Views: 80

Answers (2)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476557

Given you want to calculate the sum of the Finances with the same Stock as the Stock of the Stats object, you can calculate this with:

from django.db.models import Sum

@property
def earnings_per_share(self):
    return Finance.objects.filter(
        stock_id=self.stock_id
    ).aggregate(
        total=Sum('net_income')
    )['total'] / self.shares_outstanding

or a more descriptive filter:

from django.db.models import Sum

@property
def earnings_per_share(self):
    return Finance.objects.filter(
        stock__stats=self
    ).aggregate(
        total=Sum('net_income')
    )['total'] / self.shares_outstanding

If no all Stats objects have one or more Finance objects, then the Sum will return None (NULL), in that case we probably want to return 0 instead. We can use the Coalesce [Django-doc] function for this:

from django.db.models import Coalesce, Sum, Value

@property
def earnings_per_share(self):
    return Finance.objects.filter(
        stock__stats=self
    ).aggregate(
        total=Coalesce(Sum('net_income'), Value(0))
    )['total'] / self.shares_outstanding

Upvotes: 1

ruddra
ruddra

Reputation: 51948

Try like this:

@property
def earnings_per_share(self):
   total_earnings_per_share = 0 
   for finance in self.stock.finance_set.all():
         total_earnings_per_share += finance.net_income / self.shares_outstanding
   return total_earnings_per_share

Well, you will not get a single instance of Finance, because it is Foreign Key between Finance and Stock, meaning one stock can have multiple finance.

Upvotes: 3

Related Questions