如何在Python / Django的会计层次结构中为多个级别的父节点创建一个子节点总和?
我目前有一个显示单个帐户总和的应用程序,但是这些值未添加到父级帐户中。
该应用具有以下型号:
from django.db import models
class accounts(models.Model):
account_nr = models.IntegerField(null=True)
account_name = models.CharField(max_length=100)
account_parent_nr = models.IntegerField(null=True)
class transactions(models.Model):
transaction_id = models.CharField(max_length=100)
account_ID = models.ForeignKey(accounts, on_delete=models.CASCADE)
debit_value = models.DecimalField(max_digits=10, decimal_places=2)
credit_value = models.DecimalField(max_digits=10, decimal_places=2)
一些示例数据是:
account_nr account_name account_parent_nr
1000 current assets null
1001 cash 1000
1002 bank 1000
1010 debtors 1000
1011 debtor 1 1010
1012 debtor 2 1010
3000 stock null
3010 category 1 3000
3011 product a 3010
3012 product b 3010
...
0010 equity null
0011 owner x 0010
0012 owner y 0010
交易的样本数据将是:
transaction_id account_id debit_value credit_value
1 1001 100 0
1 0011 0 100
2 1002 100 0
2 0011 0 100
3 1011 100 0
3 0011 0 100
4 1012 100 0
4 0011 0 100
5 3011 50 0
5 3012 50 0
5 0012 0 100
使用以下视图:
from django.shortcuts import render
from django.db.models import Sum
from .models import accounts, transactions
def home(request):
account_query = accounts.objects.all() \
.annotate(Sum('transactions__debit_value')) \
.annotate(Sum('transactions__credit_value')) \
.order_by('account_nr')
args = {'account_queryx': account_query}
return render(request, 'home.html', args)
以及以下模板:
{% extends "base.html" %}
{% block content %}
<table>
<tr>
<th>Account</th>
<th>Omschrijving</th>
<th>Debit</th>
<th>Credit</th>
</tr>
{% for account_query in account_queryx %}
<tr>
<td>{{ account_query.account_nr }}</td>
<td>{{ account_query.account_name }}</td>
<td>{{ account_query.transactions__debit_value__sum}}</td>
<td>{{ account_query.transactions__credit_value__sum }}</td>
</tr>
{% endfor %}
</table>
</div>
{% endblock %}
我现在得到这样的结果:
acount_id account_name debit credit
1000 current assets null null
1001 cash 100 0
1002 bank 100 0
1010 debtors null null
1011 debtor 1 100 0
1012 debtor 2 100 0
3000 stock null null
3010 category 1 null null
3011 product a 50 0
3012 product b 50 0
...
0010 equity null null
0011 owner x 0 400
0012 owner y 0 100
我最后要说的是,现在显示为null的值是子节点的总和。我更喜欢在自己的views.py中实现一个解决方案。
我一直在寻找可以帮助我解决这一问题的理论。我发现递归求和可能会有所帮助,但是我很难将其纳入工作代码中。我不明白应该使用哪种算法基于帐号/父母/子女关系创建总和。
答案 0 :(得分:0)
我认为您正在构想一种需要更复杂的数据模型的数据模型,该模型可以分辨哪些特定子帐户是父帐户的子帐户,并且需要相应地更复杂的查询才能在您访问数据库时对这些子帐户进行小计。
如果缺少此功能,我建议您基本上像现在一样获取原始数据,然后对其进行迭代以构建可用于演示的数据集,然后在小计中在视图中进行格式化...
from django.shortcuts import render
from django.db.models import Sum
from .models import accounts, transactions
def home(request):
# Get the raw account balances
account_query_raw = accounts.objects.all() \
.annotate(Sum('transactions__debit_value')) \
.annotate(Sum('transactions__credit_value')) \
.order_by('account_nr')
# Build the updated dataset with account sums
account_query = [ ]
cur_parent_index = None
for account in account_query_raw:
account_query.append( account )
if not account_query.transactions__debit_value__sum:
# new parent account...
# set null sums in parent records to zero
current_parent_index = len( account_query ) -1
parent = account_query[ cur_parent_index ]
parent.transactions__debit_value = 0
parent.transactions__credit_value = 0
elif current_parent_index:
# if we have a current parent account,
# include this account in the parent's sum
parent = account_query[ cur_parent_index ]
parent.transactions__debit_value__sum += \
account.transactions__debit_value__sum
parent.transactions__credit_value__sum += \
account.transactions__credit_value__sum
args = {'account_queryx': account_query}
return render(request, 'home.html', args)
通常有一种趋势,认为您想在数据库上进行所有此类数据操作,但是如果您必须将所有结果记录从数据库中拉回以进行渲染,那么实际上并没有太多直接在Python中将它们直接操纵成您所需的性能问题。