Обратный вызов 'upload_to' в поле FileField обращается к базе данных за связанным содержимым?
У меня есть Attachment
модель с двумя полями ForeignKey и get_attachment_path
обратным вызовом для upload_to
атрибута:
def get_attachment_path(instance, filename):
return f'{instance.owner.name}/{instance.chat.id}/{filename}'
class Attachment(models.Model):
owner = models.ForeignKey(..)
chat = models.ForeignKey(..)
file = models.FileField(upload_to=get_attachment_path, ...)
Нижеприведенная строка вызовет выполнение get_attachment_path
:
Attachment.objects.create(..., file=file)
Итак, при использовании приведенной выше строки, будет ли django обращаться к db дважды (один раз для .create
и другой раз для get_attachment_path
)? Спрашиваю это потому, что обратный вызов get_attachment_path
пытается получить доступ к связанным данным (instance.chat.id
и т.д.).
Если да, то есть ли способ оптимизировать его?
Нет, он не попадет в БД, потому что вы уже передаете существующие и сохраненные(!) Owner
и Chat
объекты в Attachment.objects.create
, поэтому обработчику загрузки не нужно извлекать их из базы данных.
Однако при получении вложения из базы данных будут сделаны дополнительные запросы на связанные объекты:
attachment = Attachment.objects.get(id=some_id)
attachment.file.save(...)
В этом случае использование select_related
может убрать лишние запросы.
Вы всегда можете проверить выполняемые SQL-запросы (только в режиме DEBUG
):
from django.db import connection
def get_attachment_path(instance, filename):
print('Queries before', connection.queries)
path = f'{instance.owner.name}/{instance.chat.id}/{filename}'
print('Queries after', connection.queries)
return path
В качестве альтернативы, Django Debug Toolbar является отличным дополнением к проекту Django для оптимизации SQL запросов.