Complete worked example
python
from bootstrap_lab import django_setup
django_setup(__name__)
from bootstrap_lab import install_models
from django.db import models, connection
from django.test.utils import CaptureQueriesContext
class Company(models.Model):
name = models.CharField(max_length=40)
class Meta:
app_label = "framework_lab"
class Role(models.Model):
company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name="roles")
class Meta:
app_label = "framework_lab"
install_models(Company, Role)
def relation_counts(names):
Role.objects.all().delete()
Company.objects.all().delete()
for index, name in enumerate(names, 1):
company = Company.objects.create(id=index, name=name)
Role.objects.create(id=index, company=company)
Company.objects.create(id=len(names) + 1, name="Empty")
with CaptureQueriesContext(connection) as forward:
selected = [role.company.name for role in Role.objects.select_related("company").order_by("id")]
with CaptureQueriesContext(connection) as reverse:
groups = [[company.id, len(company.roles.all())] for company in Company.objects.prefetch_related("roles").order_by("id")]
return {"names": selected, "groups": groups, "forward_queries": len(forward), "reverse_queries": len(reverse)}- Reasoning
- select_related joins the single company for each selected role, allowing the forward rendering pass to use one query in this fixture. prefetch_related separately fetches companies and their role collections, then associates them in Python.