Hi everyone!
I have a base queryset
and the goal is to build a dashboard statistic using the base queryset
but filtered by different values for each variable.
My simplified code for better understanding:
class Transaction(models.Model):
user = models.ForeignKey(CustomUser, related_name="transactions", on_delete=models.CASCADE)
title = models.CharField(max_length=32, verbose_name="Title")
category = models.ForeignKey(Category, related_name="transactions", on_delete=models.CASCADE, null=True, blank=True)
operation = models.CharField(max_length=8, choices=OPERATION_TYPE, verbose_name="operation")
value = models.DecimalField(max_digits=14, decimal_places=2, verbose_name="value")
date_created = models.DateTimeField(auto_now_add=True, blank=True, null=True)
class Category(MPTTModel):
name = models.CharField(max_length=54, unique=True)
parent = TreeForeignKey("self", on_delete=models.CASCADE, null=True, blank=True, related_name='children')
Having the models above I’ve created ClassBasedView(ListView)
:
class DashboardView(ListView):
model = Transaction
template_name = "invoices/dashboard.html"
ordering = "-date_created"
def get_queryset(self) -> QuerySet[Any]:
queryset = super().get_queryset()
queryset = queryset.filter(user=self.request.user).select_related("category__parent")
return queryset
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
data = super().get_context_data(**kwargs)
# retrieving all transactons
transactions_all = self.get_queryset()
# retrieving incomes/expenses summary for current month
incomes_this_month = transactions_all.filter(transaction_filter.transaction_date_filter(month="current"), operation="incomes")
incomes_this_month_sum = incomes_this_month.aggregate(Sum("value")).get("value__sum")
expenses_this_month = transactions_all.filter(transaction_filter.transaction_date_filter(month="current"), operation="expenses")
expenses_this_month_sum = expenses_this_month.aggregate(Sum("value")).get("value__sum")
# retrieving incomes/expenses summary for previous month
transactions_prev_month = transactions_all.filter(transaction_filter.transaction_date_filter(month="previous"))
incomes_previous_month = transactions_prev_month.filter(operation="incomes")
incomes_previous_month_sum = incomes_previous_month.aggregate(Sum("value")).get("value__sum")
expenses_previous_month = transactions_prev_month.filter(operation="expenses")
expenses_previous_month_sum = expenses_previous_month.aggregate(Sum("value")).get("value__sum")
You can see transaction_date_filter
in filter()
manager. It’s just a Q()
objects for date filtering.
Using select_related
I managed to remove duplicates but there are still “similar” queries as Django ORM requests individual queries to filter incomes_this_month
, expenses_this_month
, incomes_previous_month
and expenses_previous_month
by date=
and operation=
fields. I’m aware that filter()
manager “resets” cached objects so I’m trying to find a more efficient way to get such a data withoud hitting a DB with extra queries. I’ve attached DjDT query counter screenshot. Hope it makes the question more clear.
Appreciate any suggestion on this topic.