Уявімо, що для аутентифицированного користувача ппрі відкритті сторінок постійно виконуються якісь запити, наприклад подгружается додатково список повідомлень, а також його профіль. І цю інформацію ми використовуємо в шаблонах, наприклад таким чином.
{% if user.is_authenticated %} {{ user.profile.avatar }} {{ user.notices.count }} {% endif %}
Як profile, так і notices - це моделі даних, для яких потрібно виконати запит до бази даних, а кожен запит - це додаткове підключення і додаткова вибірка даних, що збільшує час відгуку сайту. При цьому в Django для прискорення вибірок використовується механізм вибірки відповідних моделей в одному запиті до бази даних.
Виходить, що три початкових запиту можна об'єднати в один запит. Але якщо зі звичайними моделями все більш-менш зрозуміло, то з об'єктом аутентифицированного користувача виникає проблема, оскільки на перший погляд не ясно, коли і де забираються дані про користувача.
Відповідь: аутентіфіцированний користувач забирається в бекенд аутентифікації.
Тому нам потрібно написати власний бекенд аутентифікації, щоб було можна виконати select і prefetch запити при пошуку користувача.
Це буде виглядати наступним чином.
# -*- coding: utf-8 -*- from django.contrib.auth import get_user_model class MyBackend: def get_user(self, user_id): try: return get_user_model().objects.select_related('profile').prefetch_related('notices').get(pk=user_id) except get_user_model().DoesNotExist: return None
А щоб це запрацювало, потрібно додати наш бекенд аутентифікації в налаштуваннях.
AUTHENTICATION_BACKENDS = ( 'my_app.backends.MyBackend', 'django.contrib.auth.backends.ModelBackend', )