优化 django sql 查询
optimise django sql query
我正在使用 Django 2.x.
我有两个模型
class AmountGiven(models.Model):
contact = models.ForeignKey(Contact, on_delete=models.PROTECT)
amount = models.FloatField(help_text='Amount given to the contact')
interest_rate = models.FloatField(blank=True, default=None, null=True)
given_date = models.DateField(default=timezone.now)
total_due = models.FloatField(blank=True, default=0.0, editable=False)
class AmountReturned(models.Model):
amount_given = models.ForeignKey(AmountGiven, on_delete=models.CASCADE, blank=True)
amount = models.FloatField()
return_date = models.DateField(default=date.today)
用例
- 给一个联系人的金额可以有多个记录
- 给定的金额可以有多个返回金额的记录
现在,我想获取特定联系人的 total_due
金额。 这包括
total_payable = total_given + interest
total_due = total_payable - total_returned
为了计算total_due
和interest
,我在AmountGiven[=62]中定义了几个属性方法=] 模型.
@property
def interest_to_pay(self):
if self.interest_rate:
simple_interest_amount = ...
return simple_interest_amount
return 0
@property
def total_payable(self):
return self.amount + self.interest_to_pay
@property
def amount_due(self):
total_due = self.total_payable - self.total_returned
self.total_due = total_due
self.save()
return total_due
@property
def total_returned(self):
returned_amount = self.amountreturned_set.aggregate(total_returned=Sum('amount'))['total_returned']
if not returned_amount:
returned_amount = 0
return returned_amount
在 Contact 模型中,有一个 属性 方法来获取联系人的总应付金额。
@property
def amount_due(self):
total_due = 0
for due in self.amountgiven_set.all():
total_due += due.amount_due
return total_due
查询
ContactSerializer
class ContactMinSerializer(serializers.ModelSerializer):
class Meta:
model = Contact
fields = (
'id', 'first_name', 'amount_due', 'created', 'modified'
)
由于 amount_due
属性 在 ContactSerializer
中使用,因此每次调用联系人时都会调用 amount_due
属性,从而导致嵌套数据库查询。
如何优化应用程序中的上述场景以减少获取联系人或联系人列表时的数据库查询?特别是两个属性 amount_due 和 total_returned.
amount_due() 每次更新 total_due 字段 table它被称为。
Edit 2
class ContactViewSet(LoggingMixin, viewsets.ModelViewSet):
serializer_class = ContactMinSerializer
def get_queryset(self):
return Contact.objects.filter(user=self.request.user).annotate(
total_due=Sum(
F('amountgiven_set__total_payable')
- F('amountgiven_set__total_returned')
)
).order_by('first_name')
You're looking for annotations.
您的视图集应按如下方式定义查询集:
from django.db.models import F, Sum
Contact.objects.annotate(
total_due=Sum(
F('amountgiven_set__total_payable')
- F('amountgiven_set__total_returned')
)
)
然后在序列化器上定义一个 MethodSerializer 字段来解决它。
class ContactMinSerializer(serializers.ModelSerializer):
total_due = serializers.SerializerMethodField()
def get_total_due(self, obj):
return return self.total_due
class Meta:
model = Contact
fields = (
'id', 'first_name', 'created', 'modified',
'total_due',
)
我正在使用 Django 2.x.
我有两个模型
class AmountGiven(models.Model):
contact = models.ForeignKey(Contact, on_delete=models.PROTECT)
amount = models.FloatField(help_text='Amount given to the contact')
interest_rate = models.FloatField(blank=True, default=None, null=True)
given_date = models.DateField(default=timezone.now)
total_due = models.FloatField(blank=True, default=0.0, editable=False)
class AmountReturned(models.Model):
amount_given = models.ForeignKey(AmountGiven, on_delete=models.CASCADE, blank=True)
amount = models.FloatField()
return_date = models.DateField(default=date.today)
用例
- 给一个联系人的金额可以有多个记录
- 给定的金额可以有多个返回金额的记录
现在,我想获取特定联系人的 total_due
金额。 这包括
total_payable = total_given + interest
total_due = total_payable - total_returned
为了计算total_due
和interest
,我在AmountGiven[=62]中定义了几个属性方法=] 模型.
@property
def interest_to_pay(self):
if self.interest_rate:
simple_interest_amount = ...
return simple_interest_amount
return 0
@property
def total_payable(self):
return self.amount + self.interest_to_pay
@property
def amount_due(self):
total_due = self.total_payable - self.total_returned
self.total_due = total_due
self.save()
return total_due
@property
def total_returned(self):
returned_amount = self.amountreturned_set.aggregate(total_returned=Sum('amount'))['total_returned']
if not returned_amount:
returned_amount = 0
return returned_amount
在 Contact 模型中,有一个 属性 方法来获取联系人的总应付金额。
@property
def amount_due(self):
total_due = 0
for due in self.amountgiven_set.all():
total_due += due.amount_due
return total_due
查询
ContactSerializer
class ContactMinSerializer(serializers.ModelSerializer):
class Meta:
model = Contact
fields = (
'id', 'first_name', 'amount_due', 'created', 'modified'
)
由于 amount_due
属性 在 ContactSerializer
中使用,因此每次调用联系人时都会调用 amount_due
属性,从而导致嵌套数据库查询。
如何优化应用程序中的上述场景以减少获取联系人或联系人列表时的数据库查询?特别是两个属性 amount_due 和 total_returned.
amount_due() 每次更新 total_due 字段 table它被称为。
Edit 2
class ContactViewSet(LoggingMixin, viewsets.ModelViewSet):
serializer_class = ContactMinSerializer
def get_queryset(self):
return Contact.objects.filter(user=self.request.user).annotate(
total_due=Sum(
F('amountgiven_set__total_payable')
- F('amountgiven_set__total_returned')
)
).order_by('first_name')
You're looking for annotations.
您的视图集应按如下方式定义查询集:
from django.db.models import F, Sum
Contact.objects.annotate(
total_due=Sum(
F('amountgiven_set__total_payable')
- F('amountgiven_set__total_returned')
)
)
然后在序列化器上定义一个 MethodSerializer 字段来解决它。
class ContactMinSerializer(serializers.ModelSerializer):
total_due = serializers.SerializerMethodField()
def get_total_due(self, obj):
return return self.total_due
class Meta:
model = Contact
fields = (
'id', 'first_name', 'created', 'modified',
'total_due',
)