When you use the dot notation in @hook
decorator for the related fields (ForeignKey or OneToOneField) it hits the database for every object separately. It doesn't matter if you use select_related
or not.
Here are the models to test:
from django.contrib.auth.models import User
from django.db import models
from django_lifecycle import LifecycleModel, hook, AFTER_SAVE
class Organization(models.Model):
name = models.CharField(max_length=250)
class Profile(LifecycleModel):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
employer = models.ForeignKey(Organization, on_delete=models.SET_NULL, null=True)
bio = models.TextField(null=True, blank=True)
age = models.PositiveIntegerField(null=True, blank=True)
@hook(AFTER_SAVE, when='user.first_name', has_changed=True)
@hook(AFTER_SAVE, when='user.last_name', has_changed=True)
def user_changed(self):
print('User was changed')
@hook(AFTER_SAVE, when='employer.name', has_changed=True)
def employer_changed(self):
print('Employer was changed')
What I got when tried to fetch profiles (with db queries logging):
>>> from main.models import Profile
>>> queryset = Profile.objects.all()[:10]
>>> queryset
(0.000) SELECT "main_profile"."id", "main_profile"."user_id", "main_profile"."employer_id", "main_profile"."bio", "main_profile"."age" FROM "main_profile" LIMIT 10; args=(); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 2 LIMIT 21; args=(2,); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 3 LIMIT 21; args=(3,); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 4 LIMIT 21; args=(4,); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 5 LIMIT 21; args=(5,); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 6 LIMIT 21; args=(6,); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 7 LIMIT 21; args=(7,); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 8 LIMIT 21; args=(8,); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 9 LIMIT 21; args=(9,); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 10 LIMIT 21; args=(10,); alias=default
<QuerySet [<Profile: Profile object (1)>, <Profile: Profile object (2)>, <Profile: Profile object (3)>, <Profile: Profile object (4)>, <Profile: Profile object (5)>, <Profile: Profile object (6)>, <Profile: Profile object (7)>, <Profile: Profile object (8)>, <Profile: Profile object (9)>, <Profile: Profile object (10)>]>
>>> queryset = Profile.objects.select_related('user')[:10]
>>> queryset
(0.001) SELECT "main_profile"."id", "main_profile"."user_id", "main_profile"."employer_id", "main_profile"."bio", "main_profile"."age", "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "main_profile" LEFT OUTER JOIN "auth_user" ON ("main_profile"."user_id" = "auth_user"."id") LIMIT 10; args=(); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 2 LIMIT 21; args=(2,); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 3 LIMIT 21; args=(3,); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 4 LIMIT 21; args=(4,); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 5 LIMIT 21; args=(5,); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 6 LIMIT 21; args=(6,); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 7 LIMIT 21; args=(7,); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 8 LIMIT 21; args=(8,); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 9 LIMIT 21; args=(9,); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 10 LIMIT 21; args=(10,); alias=default
<QuerySet [<Profile: Profile object (1)>, <Profile: Profile object (2)>, <Profile: Profile object (3)>, <Profile: Profile object (4)>, <Profile: Profile object (5)>, <Profile: Profile object (6)>, <Profile: Profile object (7)>, <Profile: Profile object (8)>, <Profile: Profile object (9)>, <Profile: Profile object (10)>]>
>>> queryset = Profile.objects.select_related('user', 'employer')[:10]
>>> queryset
(0.001) SELECT "main_profile"."id", "main_profile"."user_id", "main_profile"."employer_id", "main_profile"."bio", "main_profile"."age", "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined", "main_organization"."id", "main_organization"."name" FROM "main_profile" LEFT OUTER JOIN "auth_user" ON ("main_profile"."user_id" = "auth_user"."id") LEFT OUTER JOIN "main_organization" ON ("main_profile"."employer_id" = "main_organization"."id") LIMIT 10; args=(); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 2 LIMIT 21; args=(2,); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 3 LIMIT 21; args=(3,); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 4 LIMIT 21; args=(4,); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 5 LIMIT 21; args=(5,); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 6 LIMIT 21; args=(6,); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 7 LIMIT 21; args=(7,); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 8 LIMIT 21; args=(8,); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 9 LIMIT 21; args=(9,); alias=default
(0.000) SELECT "main_organization"."id", "main_organization"."name" FROM "main_organization" WHERE "main_organization"."id" = 1 LIMIT 21; args=(1,); alias=default
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 10 LIMIT 21; args=(10,); alias=default
<QuerySet [<Profile: Profile object (1)>, <Profile: Profile object (2)>, <Profile: Profile object (3)>, <Profile: Profile object (4)>, <Profile: Profile object (5)>, <Profile: Profile object (6)>, <Profile: Profile object (7)>, <Profile: Profile object (8)>, <Profile: Profile object (9)>, <Profile: Profile object (10)>]>