Joh*_*han 6 sql django postgresql django-models django-orm
假设我有一个具有以下模型定义的事务列表:
class Transaction(models.Model):
amount = models.FloatField()
client = models.ForeignKey(Client)
date = models.DateField()
description = models.CharField()
invoice = models.ForeignKey(Invoice, null=True)
Run Code Online (Sandbox Code Playgroud)
现在我想在月底为每个客户创建发票.发票模型如下所示:
class Invoice(models.Model):
client = models.ForeignKey(Client)
invoice_date = models.DateField()
invoice_number = models.CharField(unique=True)
def amount_due(self):
return self.transaction_set.aggregate(Sum('amount'))
def create_invoices(invoice_date):
for client in Client.objects.all():
transactions = Transaction.objects.filter(client=client)
if transactions.exists():
invoice = Invoice(client=client, number=get_invoice_number(), date=invoice_date)
invoice.save()
transactions.update(invoice=invoice)
Run Code Online (Sandbox Code Playgroud)
我知道我可以通过批量创建在1个查询中创建批量创建的所有发票,但我仍然需要单独在交易模型中设置发票字段.
在创建所有发票后,是否可以使用单个查询设置所有交易模型的发票字段?最好在使用ORM时,但如果需要,很乐意使用原始SQL.
我知道我也可以在交易清单上使用逐个客户来获取每个客户的总数,但随后各个条目都没有链接到发票.
如果您之前能够生成从客户到发票的映射,则可以尝试构建条件更新查询:
from django.db.models import Case, Value, When
# generate this after creating the invoices
client_invoice_mapping = {
# client: invoice
}
cases = [When(client_id=client.pk, then=Value(invoice.pk))
for client, invoice in client_invoice_mapping.items()]
Transaction.objects.update(invoice_id=Case(*cases))
Run Code Online (Sandbox Code Playgroud)
请注意,条件查询从 Django 1.8 开始可用。否则,您可能会考虑使用原始 SQL 构建类似的东西。
补充@Bernhard Vallant的答案.您只能使用3个查询.
def create_invoices(invoice_date):
# Maybe use Exists clause here instead of subquery,
# do some tests for your case if the query is slow
clients_with_transactions = Client.objects.filter(
id__in=Transaction.objects.values('client')
)
invoices = [
Invoice(client=client, number=get_invoice_number(), date=invoice_date)
for client in clients_with_transactions
]
# With PostgreSQL Django can populate id's here
invoices = Invoice.objects.bulk_create(invoices)
# And now use a conditional update
cases = [
When(client_id=invoice.client_id, then=Value(invoice.pk))
for invoice in invoices
]
Transaction.objects.update(invoice_id=Case(*cases))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
240 次 |
| 最近记录: |