Django: невозможно выполнить вычисление внутри шаблона

Я создал Django-приложение для электронной коммерции, и в бэк-офисе этого приложения у меня есть страница, которая должна показывать некоторые статистические данные. Я пытаюсь отобразить выгоду или убытки. Для затрат я создал @свойство в модели следующим образом:

class Statistics(models.Model):
    """
    The Statistics model represents the statistics that can be calculated
    """
    costs_infra = models.FloatField(verbose_name="Costs Infrastructure")
    costs_salary = models.FloatField(verbose_name="Costs Salary")

    class Meta:
        verbose_name_plural = "Statistics"   

    def __str__(self):
        """Unicode representation of Statistics"""

        return " Infra costs: {}, Salary costs: {}".format(
                self.costs_infra,
                self.costs_salary
            )
    
    @property
    def calculate_costs(self):
        return self.costs_infra + self.costs_salary

Для общего дохода, я рассчитал его внутри представления следующим образом:

@group_required('Administrator', 'Manager')
def stats_home(request):

    total_users = User.objects.all().count()
    costs = Statistics.objects.all()
    subscriptions_1month = Subscription.objects.get(plan_name='1 Month')
    subscriptions_1year = Subscription.objects.get(plan_name='1 Year')
    subscriptions_3year = Subscription.objects.get(plan_name='3 Years')
    user_subscriptions_1month = UserSubscription.objects.filter(subscription=subscriptions_1month).annotate(Count('user', distinct=True)).count()
    user_subscriptions_1year = UserSubscription.objects.filter(subscription=subscriptions_1year).annotate(Count('user', distinct=True)).count()
    user_subscriptions_3years = UserSubscription.objects.filter(subscription=subscriptions_3year).annotate(Count('user', distinct=True)).count()

    income_per_subscription_1month = Subscription.objects.get(plan_name='1 Month').price * UserSubscription.objects.filter(subscription=subscriptions_1month).count()
    income_per_subscription_1year = Subscription.objects.get(plan_name='1 Year').price * UserSubscription.objects.filter(subscription=subscriptions_1year).count()
    income_per_subscription_3years = Subscription.objects.get(plan_name='3 Years').price * UserSubscription.objects.filter(subscription=subscriptions_3year).count()
    
    total_income = income_per_subscription_1month + income_per_subscription_1year + income_per_subscription_3years

    return render (request, "stats_home.html", locals())

Наконец, я пытаюсь сделать простой расчет (общий доход - общие расходы), но я не могу сделать это внутри шаблона, насколько я мог видеть и мои исследования привели меня.

{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% load has_group %}

{% block title %} Statistics Home {% endblock %}

{% block content %}

    <div class="card border-dark mb-4" id="profil">
        <h5 class="card-header bg-dark text-white">Total number of users subscribed to the site:</h5>
        <div class="card-body">
         {{total_users}}
        </div>
    </div>

    <div class="card border-dark mb-4" id="profil">
        <h5 class="card-header bg-dark text-white">Total number of users per subscription type:</h5>
        <div class="card-body">
        <br>1 Month: {{user_subscriptions_1month}}
        <br>1 Year: {{user_subscriptions_1year}}
        <br>3 Years: {{user_subscriptions_3years}}
        </div>
    </div>

    <div class="card border-dark mb-4" id="profil">
        <h5 class="card-header bg-dark text-white">Costs:</h5>
        <div class="card-body">
            {% for cost in costs %}
            <p>Infrastructure Costs: {{cost.costs_infra}}</p>
            <p>Salary Costs: {{cost.costs_salary}}</p>
            <p>Total Costs: {{cost.calculate_costs}}</p>
            {% endfor %}
        </div>
    </div>

    <div class="card border-dark mb-4" id="profil">
        <h5 class="card-header bg-dark text-white">  Total Income: </h5>
        <div class="card-body">
          {{total_income}}
        </div>
    </div>

    <div class="card border-dark mb-4" id="profil">
        <h5 class="card-header bg-dark text-white">  Benefits/Loss: </h5>
        <div class="card-body">
            Benefits/Loss: {{total_income - cost.calculate_costs}}
        </div>
    </div>

При выполнении {{total_income - cost.calculate_costs}} я получаю ошибку

Не удалось разобрать остаток: ' - cost.calculate_costs' из 'total_income - cost.calculate_costs'

Дело в том, что я могу получить общие расходы с помощью {{cost.calculate_costs}} и общий доход с помощью {{total_income}}, но почему-то я не могу сделать простую подстановку внутри шаблона.

Каким образом лучше всего этого достичь?

Лучшее, что вы можете сделать, это вместо вычислений в шаблонах сделать это в представлениях, поскольку рекомендуется не делать этого в шаблонах, поскольку это уменьшит производительность сайта делайте это вместо этого:

views.py

variable = total_income - total_costs
context = {"variable":variable}
return render(request, "stats_home.html", locals(), context)

Ваша проблема заключается в том, что вы пытаетесь получить доступ к cost.calculate_costs вне цикла {% for cost in costs %}. Поскольку cost не объявлен, вы получаете эту ошибку. Вдобавок ко всему, django не поддерживает вычисления в шаблоне - причина в том, что лучше всего держать логику полностью в представлениях и оставлять только представление в шаблонах. Однако есть фильтр дополнений, но вам все равно нужно вычислять total_costs.

Ваше решение - рассчитать total_profit на взгляд:

def stats_home(request):
    ...
    total_costs = sum(cost.calculate_costs for cost in costs)
    total_profit = total_income - total_costs

    return render (request, "stats_home.html", locals())
<div class="card border-dark mb-4" id="profil">
    <h5 class="card-header bg-dark text-white"> Benefits/Loss: </h5>
    <div class="card-body">
        Benefits/Loss: {{ total_profit }}
    </div>
</div>
Вернуться на верх