I used the django debug toolbar to analyse why the calls to my usermodel were so painfully slow within the django admin. There I saw that I had hundreds of duplicate calls to the content_type model:
SELECT ••• FROM "django_content_type" WHERE "django_content_type"."id" = 1 LIMIT 21 362 similar queries. Duplicated 4 times.
To be honest, I do not understand where these calls come from in the first place but I wanted to pre_fetch the model. However, this seems not to be possible in the normal way because there is actually no ForeignKey or any other kind of direct relationship between the models. How could I reduce those 362 content_type calls?
This is the usermodel in question:
class User(AbstractBaseUser, PermissionsMixin):
"""
Base model for the user application
"""
USERNAME_FIELD = "email"
objects = UserManager()
username_validator = None
username = None
email = models.EmailField(_("email address"), unique=True)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(default=timezone.now)
first_name = models.CharField(max_length=150, blank=True)
last_name = models.CharField(max_length=150, blank=True)
title_of_person = models.ForeignKey(
TitleOfPerson, on_delete=models.CASCADE, blank=True, null=True
)
is_verified = models.BooleanField(default=False)
language = models.ForeignKey(
Language, blank=True, null=True, on_delete=models.SET_NULL
)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = _("User")
verbose_name_plural = _("Users")
def __str__(self) -> str:
return self.email
Thanks
In your UserAdmin
class, add a UserCreationForm
for your User
model.
Like,
from django.contrib.auth.admin import (
UserAdmin as BaseUserAdmin, UserChangeForm as BaseUserChangeForm,
UserCreationForm as BaseUserCreationForm
)
class UserChangeForm(BaseUserChangeForm):
class Meta:
model = User
fields = '__all__'
def clean_email(self):
data = self.cleaned_data.get('email')
return data.lower()
class UserAdmin(BaseUserAdmin):
form = UserChangeForm
... other fields...
This should fix your query problem.
Actual part that fixes the problem:
In the default UserChangeForm
, inside the __init__
method, the user_permissions
queryset is being initilised with select_related
optimization.
class UserChangeForm(forms.ModelForm):
password = ReadOnlyPasswordHashField(
label=_("Password"),
help_text=_(
"Raw passwords are not stored, so there is no way to see this "
"user’s password, but you can change the password using "
'<a href="{}">this form</a>.'
),
)
class Meta:
model = User
fields = "__all__"
field_classes = {"username": UsernameField}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
password = self.fields.get("password")
if password:
password.help_text = password.help_text.format("../password/")
user_permissions = self.fields.get("user_permissions")
if user_permissions:
user_permissions.queryset =
user_permissions.queryset.select_related(
"content_type"
)