Я использую 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 модель.
@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
В Контакт модель, есть свойство метод для получения общей суммы задолженности для контакта.
@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 в таблице каждый разэто называется.
Редактировать 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')