Django page reloading too long
Question:
I have some issues with the reloading time in some page in Django, it takes too long.
I use debug_toolbar and shows me Browser timing request: 4 (+113577)
models.py
class Subsidiary(models.Model):
name = models.CharField(unique=True, max_length=100, blank=False)
def __str__(self):
return self.name
class Department(models.Model):
name = models.CharField(unique=True, max_length=200, blank=False,)
def __str__(self):
return self.name
class SubBudget(models.Model):
name = models.CharField(max_length=100, unique=True, blank=False)
def __str__(self):
return self.name
class SubBudgetOwner(models.Model):
budget_owner = models.ForeignKey(Person, models.PROTECT, related_name="budgets_owned")
sub_budget_owner = models.ForeignKey(Person, models.PROTECT, related_name="sub_budgets_owned")
class Meta:
ordering = ["id"]
unique_together = (("budget_owner", "sub_budget_owner"),)
verbose_name = "Budget Owner" # Title on the maint page for this table
verbose_name_plural = "Budget Owners" # Title for the navbar navigation
def __str__(self):
return str(self.budget_owner) + " - " + str(self.sub_budget_owner)
class Combination(models.Model):
id = models.AutoField(primary_key=True)
subsidiary = models.ForeignKey(Subsidiary, verbose_name="Subsidiary", null=True, blank=True, on_delete=models.CASCADE,)
department = models.ForeignKey(Department, verbose_name="Department", on_delete=models.CASCADE,)
sub_budget = models.ForeignKey(SubBudget, verbose_name="Sub Budget", on_delete=models.CASCADE,)
budget_owner = models.ForeignKey(SubBudgetOwner, verbose_name="Budget Owner & Sub Budget Owner", null=True, blank=True, on_delete=models.CASCADE,)
def __str__(self):
return (f"{self.subsidiary} {self.department} {self.sub_budget} {self.budget_owner}")
class Meta:
ordering = ["id"]
My views.py
class CombinationListView(LoginRequiredMixin, ListView):
model = Combination
template_name = "budget/combination_list.html"
combination_list.html
{% for combination in object_list %}
<tr>
<td>{{ combination.id }}</td>
<td>{{ combination.subsidiary }}</td>
<td>{{ combination.department }}</td>
<td>{{ combination.sub_budget }}</td>
<td>{{ combination.budget_owner }}</td>
</tr>
{% endfor %}
I think maybe all the ForeignKeys do it so slow…
What can I do to improve it?
Answers:
You are making 11k queries in this page. This takes 46 seconds. You should start by lower the number of requests.
You should start by checking if you can use select_related
or prefetch_related
to improve the requests generated by your template.
So I found a solution.
I added queryset function (CombinationQuerySet) and it makes a magic
In my model.py:
class CombinationQuerySet(models.QuerySet):
def fast(self):
return self.select_related(
"subsidiary",
"department",
"sub_budget",
"budget_owner__budget_owner",
"budget_owner__sub_budget_owner",
)
class Combination(models.Model):
id = models.AutoField(primary_key=True)
subsidiary = models.ForeignKey(Subsidiary, verbose_name="Subsidiary", null=True, blank=True, on_delete=models.CASCADE,)
department = models.ForeignKey(Department, verbose_name="Department", on_delete=models.CASCADE,)
sub_budget = models.ForeignKey(SubBudget, verbose_name="Sub Budget", on_delete=models.CASCADE,)
budget_owner = models.ForeignKey(SubBudgetOwner, verbose_name="Budget Owner & Sub Budget Owner", null=True, blank=True, on_delete=models.CASCADE,)
objects = CombinationQuerySet.as_manager()
def __str__(self):
return (f"{self.subsidiary} {self.department} {self.sub_budget} {self.budget_owner}")
class Meta:
ordering = ["id"]
my view.py (added the line: queryset = Combination.objects.fast()):
class CombinationListView(LoginRequiredMixin, ListView):
model = Combination
template_name = "budget/combination_list.html"
queryset = Combination.objects.fast()
I saw it improved the page loading much faster (1 sec even less)!
def fast(self): is really helpful and used in my app.
return self.select_related was because a foreign keys and make it faster in the quary
I have some issues with the reloading time in some page in Django, it takes too long.
I use debug_toolbar and shows me Browser timing request: 4 (+113577)
models.py
class Subsidiary(models.Model):
name = models.CharField(unique=True, max_length=100, blank=False)
def __str__(self):
return self.name
class Department(models.Model):
name = models.CharField(unique=True, max_length=200, blank=False,)
def __str__(self):
return self.name
class SubBudget(models.Model):
name = models.CharField(max_length=100, unique=True, blank=False)
def __str__(self):
return self.name
class SubBudgetOwner(models.Model):
budget_owner = models.ForeignKey(Person, models.PROTECT, related_name="budgets_owned")
sub_budget_owner = models.ForeignKey(Person, models.PROTECT, related_name="sub_budgets_owned")
class Meta:
ordering = ["id"]
unique_together = (("budget_owner", "sub_budget_owner"),)
verbose_name = "Budget Owner" # Title on the maint page for this table
verbose_name_plural = "Budget Owners" # Title for the navbar navigation
def __str__(self):
return str(self.budget_owner) + " - " + str(self.sub_budget_owner)
class Combination(models.Model):
id = models.AutoField(primary_key=True)
subsidiary = models.ForeignKey(Subsidiary, verbose_name="Subsidiary", null=True, blank=True, on_delete=models.CASCADE,)
department = models.ForeignKey(Department, verbose_name="Department", on_delete=models.CASCADE,)
sub_budget = models.ForeignKey(SubBudget, verbose_name="Sub Budget", on_delete=models.CASCADE,)
budget_owner = models.ForeignKey(SubBudgetOwner, verbose_name="Budget Owner & Sub Budget Owner", null=True, blank=True, on_delete=models.CASCADE,)
def __str__(self):
return (f"{self.subsidiary} {self.department} {self.sub_budget} {self.budget_owner}")
class Meta:
ordering = ["id"]
My views.py
class CombinationListView(LoginRequiredMixin, ListView):
model = Combination
template_name = "budget/combination_list.html"
combination_list.html
{% for combination in object_list %}
<tr>
<td>{{ combination.id }}</td>
<td>{{ combination.subsidiary }}</td>
<td>{{ combination.department }}</td>
<td>{{ combination.sub_budget }}</td>
<td>{{ combination.budget_owner }}</td>
</tr>
{% endfor %}
I think maybe all the ForeignKeys do it so slow…
What can I do to improve it?
You are making 11k queries in this page. This takes 46 seconds. You should start by lower the number of requests.
You should start by checking if you can use select_related
or prefetch_related
to improve the requests generated by your template.
So I found a solution.
I added queryset function (CombinationQuerySet) and it makes a magic
In my model.py:
class CombinationQuerySet(models.QuerySet):
def fast(self):
return self.select_related(
"subsidiary",
"department",
"sub_budget",
"budget_owner__budget_owner",
"budget_owner__sub_budget_owner",
)
class Combination(models.Model):
id = models.AutoField(primary_key=True)
subsidiary = models.ForeignKey(Subsidiary, verbose_name="Subsidiary", null=True, blank=True, on_delete=models.CASCADE,)
department = models.ForeignKey(Department, verbose_name="Department", on_delete=models.CASCADE,)
sub_budget = models.ForeignKey(SubBudget, verbose_name="Sub Budget", on_delete=models.CASCADE,)
budget_owner = models.ForeignKey(SubBudgetOwner, verbose_name="Budget Owner & Sub Budget Owner", null=True, blank=True, on_delete=models.CASCADE,)
objects = CombinationQuerySet.as_manager()
def __str__(self):
return (f"{self.subsidiary} {self.department} {self.sub_budget} {self.budget_owner}")
class Meta:
ordering = ["id"]
my view.py (added the line: queryset = Combination.objects.fast()):
class CombinationListView(LoginRequiredMixin, ListView):
model = Combination
template_name = "budget/combination_list.html"
queryset = Combination.objects.fast()
I saw it improved the page loading much faster (1 sec even less)!
def fast(self): is really helpful and used in my app.
return self.select_related was because a foreign keys and make it faster in the quary