[英]Queryset Union in Django
I'm trying to do a simple double entry accounting with Django.我正在尝试用 Django 做一个简单的复式记账。 Every transaction is currently one object with debit and credit accounts being foreign keys.
当前,每笔交易都是一个对象,借方和贷方帐户是外键。 Now I'm trying to get all transaction objects out so that there's debit and credit object for every transaction and I can easily order and represent every account's transactions and totals in the template.
现在我正在尝试取出所有交易对象,以便每笔交易都有借方和贷方对象,我可以轻松地在模板中订购和表示每个帐户的交易和总计。 So every transaction object needs to have debit object and credit object in the final outcome.
所以每个交易对象在最终结果中都需要有借方对象和贷方对象。 I think in MySQL you could achieve this with something like:
我认为在 MySQL 中,您可以通过以下方式实现:
SELECT date, description, amount, debit_account AS account, debit AS 1 FROM Transaction
UNION
SELECT date, description, amount, credit_account AS account, debit AS 0 FROM Transaction
What is the right way to do this with Python's objects in Django?使用 Django 中的 Python 对象执行此操作的正确方法是什么? Union seems to override the changes within the for loop I currently have and I end up with no distinction between debit and credit.
Union 似乎覆盖了我目前拥有的 for 循环中的更改,我最终没有区分借方和贷方。
models.py
class Transaction(models.Model):
date = models.DateField()
description = models.CharField(max_length=150)
debit_account = models.ForeignKey('ledger.Account', related_name='debit_account', blank=True, null=True, on_delete=models.CASCADE)
credit_account = models.ForeignKey('ledger.Account', related_name='credit_account', blank=True, null=True, on_delete=models.CASCADE)
amount = models.DecimalField(max_digits=10, decimal_places=2, default=0)
debit_in_ledger = models.BooleanField(default=False)
views.py
def ledger(request):
transaction_list_debit = Transaction.objects.all()
transaction_list_credit = Transaction.objects.all()
for a in transaction_list_debit:
a.debit_in_ledger = True
transaction_list = transaction_list_debit.union(transaction_list_credit, all=True).order_by('debit_account', 'public_date')
return render(request, 'pages/ledger.html', {'transaction_list' : transaction_list})
You can do this as follows:您可以按如下方式执行此操作:
from django.db.models import BooleanField, F, Value
q1 = Transaction.objects.annotate(
account = F('debit_account')
debit = Value(True, output_field=BooleanField())
)
q2 = Transaction.objects.annotate(
account = F('credit_account')
debit = Value(False, output_field=BooleanField())
)
qs = q1 | q2
where qs
is thus our "final" queryset.因此,
qs
是我们的“最终”查询集。 This QuerySet
will contain Transaction
objects, and every Transaction
object in the queryset will have two extra attributes: account
and debit
.这个
QuerySet
将包含Transaction
对象,queryset 中的每个Transaction
对象都有两个额外的属性: account
和debit
。 Note that other attributes like debit_account
, etc. will still exist.请注意,诸如
debit_account
等其他属性仍将存在。 Furthermore every real Transaction
in the database will thus occur twice : once from q1
, and once from q2
.此外,数据库中的每个真实
Transaction
将因此发生两次:一次来自q1
,一次来自q2
。
Furthermore the .account
will contain the primary key of the related Account
, so not a reference to the Account
.此外,
.account
将包含相关Account
的主键,因此不是对Account
的引用。 You can then fetch the Account
with Account.objects.get(pk=some_transaction.account)
.然后,您可以使用
Account.objects.get(pk=some_transaction.account)
获取Account
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.