Обратный вызов '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 запросов.