Django admin prefetch content_type model

Я использовал панель инструментов отладки django, чтобы проанализировать, почему вызовы моей модели usermodel были такими болезненно медленными в админке django. Там я увидел, что у меня были сотни дублирующих обращений к модели content_type:

SELECT --- FROM "django_content_type" WHERE "django_content_type". "id" = 1 LIMIT 21 362 похожих запросов. Дублируется 4 раза.

Честно говоря, я не понимаю, откуда вообще берутся эти вызовы, но я хотел предварительно получить модель. Однако это, похоже, невозможно обычным способом, потому что между моделями нет ни ForeignKey, ни каких-либо других прямых отношений. Как я могу сократить эти 362 вызова content_type?

Это та пользовательская модель, о которой идет речь:

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

Спасибо

В вашем классе UserAdmin добавьте UserCreationForm для вашей модели User. Например,

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...

Это должно решить вашу проблему с запросами.

Фактическая часть, устраняющая проблему:

В стандартном UserChangeForm, внутри __init__ метода, user_permissions queryset инициализируется с select_related оптимизацией.

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"
            )
Вернуться на верх