Как применить аннотации для Sum () на нескольких моделях Django? - PullRequest
1 голос
/ 18 октября 2019

У меня есть три модели django: ProjectName, ProjectBudget и ProjectActualCost.

ProjectName хранит имя проекта (т. Е. Project X).
ProjectBudget хранит имя_проекта (как внешний ключ (FK)), budget_nameи total_budget и дата для каждого бюджета. т.е. (проект X, гостиница, 600), (проект X, аренда, 500). «600» означает 600 долларов США. ProjectActualCost сохраняет каждую стоимость по мере ее возникновения (детализированные расходы) (т. Е. Гостиница: 100, аренда: 50, еда: 100) и ее дату. Таким образом, он хранит «имя_проекта» (как FK), «имя_бюджета» (как FK), фактическое_использование и дату. т.е. (проект X, гостиница, 100,10 / 03/2019), (проект X, гостиница, 100,10 / 06/2019), (проект X, аренда, 50,04 / 10/2019)

Я пытаюсь отобразить «Имя проекта», «Название бюджета», «Общий бюджет», «Всего использовано» и «Разница» в HTML-таблице. Название проекта »,« Название бюджета »,« Общий бюджет »,« Всего использовано »отображается правильно, но« Разница »отображает завышенные суммы, как показано ниже.

Модели:

class ProjectName(models.Model):
   project_name = models.CharField('Name',max_length = 15,blank = False)

  def __str__(self):
    return self.project_name 

class ProjectBudget(models.Model):
   project_name = models.ForeignKey(ProjectName,on_delete = models.CASCADE, 
          null = True)
   budget_name = models.CharField('Budget Name'max_length = 50
   total_budget =  models.DecimalField('Total Budget',max_digits = 9,decimal_places=2)

   def __str__(self):
    return self.budget_name 

class ProjectActualCost(models.Model):
   project_name = models.ForeignKey(ProjectName,on_delete = models.CASCADE, null = True)
   cost_description = models.ForeignKey(ProjectBudget,on_delete = models.CASCADE,null=True)
   actual_used = models.DecimalField('Actual Used',max_digits = 15,decimal_places = 2)

Просмотры:

def budgetview(request,project_id):
  budget_items = ProjectBudget.objects.filter(project_name_id=project_id).annotate( actual_cost=Sum('projectactualcost__actual_used'),
difference=Sum('total_budget')-Sum('projectactualcost__actual_used'))

    budget_template = "budget_view.html"

    context = {"budget_items":budget_items}

    return render(request,budget_template,context)

budget_view.html:

<table>
 <thead>
   <tr>
   <th>Project Name</th>
   <th>Budget Name</th>
   <th>Total Budget</th>
   <th>Total Used</th>
   <th>Difference</th>

   </tr>

 <tbody>
    {% for item in budget_items%}
   <tr> 
        <td>{{item.project_name}}</td>
        <td>{{item.cost_description}}</td>
        <td>{{item.total_budget}}</td>
        <td>{{item.actual_cost}}</td>
        <td>{{item.difference}}</td>

   </tr>
   {%endfor%}

 </tbody>
 </table>

Я ожидаю увидеть:

Project Name|Budget Name | Total Budget| Total Used| Difference
 Project X     Hotel        600            200        400    
 Project X     Rental       500            50         450

Но когда я рендерим budget_view.html, я получаю:

 Project Name|Budget Name | Total Budget| Total Used|Difference|
 Project X   |  Hotel     |   600       |    300    | 900  
 Project X   |  Rental    |   500       |    100    | 600 

Как правильно сделать расчеты для нескольких аннотаций sum ()? Спасибо.

1 Ответ

0 голосов
/ 18 октября 2019

Это не будет работать, потому что вы агрегируете все строки в таблице ProjectBudget. Попробуйте добавить свойство, которое обрабатывает вычисление разницы для каждого экземпляра ProjectBudget.

class ProjectBudget(models.Model):
    project_name = models.ForeignKey(ProjectName, on_delete=models.CASCADE,
                                     null=True)
    budget_name = models.CharField('Budget Name', max_length=50)
    total_budget = models.DecimalField('Total Budget', max_digits=9, decimal_places=2)

    def __str__(self):
        return self.budget_name

    @property
    def used_difference(self):
        return self.total_budget - self.projectactualcost_set.filter(cost_description=self.id)\
            .aggregate(Sum('actual_used')).get('actual_used__sum')

И обновите шаблон

<table>
    <thead>
    <tr>
        <th>Project Name</th>
        <th>Budget Name</th>
        <th>Total Budget</th>
        <th>Total Used</th>
        <th>Difference</th>
    </tr>
    <tbody>
    {% for item in budget_items %}
        <tr>
            <td>{{ item.project_name }}</td>
            <td>{{ item.budget_name }}</td>
            <td>{{ item.total_budget }}</td>
            <td>{{ item.actual_cost }}</td>
            <td>{{ item.used_difference }}</td>
        </tr>
    {% endfor %}

    </tbody>
</table>

, что дает мне

 Project Name|Budget Name | Total Budget| Total Used|Difference|
 Project X   |  Hotel     |   600       |    250    | 350  
 Project X   |  Rental    |   500       |    100    | 400 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...