Comments 15
upload_to may also be a callable, such as a function. This will be called to obtain the upload path, including the filename. This callable must accept two arguments and return a Unix-style path (with forward slashes) to be passed along to the storage system.
def user_directory_path(instance, filename):
# file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
return 'user_{0}/{1}'.format(instance.user.id, filename)
class MyModel(models.Model):
upload = models.FileField(upload_to=user_directory_path)
позволяет использовать функцию для определения пути
Тут тоже есть свои неудобства, которые описаны в упоминаемой вами документации.
instance
— In most cases, this object will not have been saved to the database yet, so if it uses the default AutoField, it might not yet have a value for its primary key field.
То есть, на момент вызова функции переданной в upload_to
, instance
еще не будет сохранен в базу, а значит, id
у него будет равен None
.
На SO есть несколько решений этой проблемы особенности, надеюсь, другие джангисты поделятся популярным самым решением.
Да на самом деле, без id в пути к файлу, обойтись можно. Урлы же потом ручками редко кто строит, а берут его из модели.
Обычная практика, вообще для имени файла какой нибудь uuid использовать, ну и по папкам разбивать (например по датам), если ожидается много файлов.
import uuid
from django.db import models
def directory_path(instance, filename):
return 'images/{0}/{1}'.format(instance.id, filename)
class MyUUIDModel(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
upload = models.FileField(upload_to=directory_path)
В базе данных можно хранить только имя картинки, а искать, где она лежит, в настройках. Я использую Flask, но большой роли это не играет. Картинки у меня — обычные строковые поля. Для каждой модели есть свой путь к папке с изображениями и подпапка, сгенерированная например из ID записи с этим полем. В итоге если мне нужно вывести в шаблон путь к картинке, это выглядит примерно так:
f'{path_to_model_images}/{x.id}/{x.image_name}'
Здесь не принято всё пихать в классы, потому что язык иначе не позволяет группировать функциональность.
можно этот момент пояснить?
Каким образом язык не позволяет группировать функциональность?
Хранение изображений с помощью Django/Django REST