Django - загрузка файла в папку с именем id объекта
Я пытался сделать это таким образом, но вместо {{product.id}} папка называется None. Я прочитал несколько статей об этом, и выяснил, что это потому, что папка создается до всего объекта. Так как же мне сделать, чтобы это работало?
models.py
def getImageURL(self, filename):
return "products_images/" + str(self.pk) + "/product_image.png"
class Product(models.Model):
name = models.CharField(max_length=200)
image = models.ImageField(upload_to=getImageURL, default="media/static/products_images/default.png" )
редактирование: изменил свою функцию на
def getImageURL(instance, filename):
return "products_images/{}/product_image.png".format(instance.id)
но это работает только при редактировании существующего объекта. Когда я пытаюсь создать новый, id устанавливается в None
Проблема заключается в следующем:
- У экземпляра еще нет первичного ключа до его создания
- Когда экземпляр будет сохранен в базе данных, тогда вы сможете получить первичный ключ
Может быть, как-то использовать сигналы? Сделать логику в представлении после его сохранения?
Альтернативный вариант для pk:
Вы можете сгенерировать UUID для объекта.
id = models.UUIDField(
primary_key = True,
default = uuid.uuid4,
editable = False)
Или альтернативно:
Посмотрите на этот пакет, вы можете установить алфавит uuid, длину и некоторые другие параметры. Это позволит вам получить доступ к id, наверняка (то же самое с uuid).
https://pypi.org/project/shortuuid/
id = ShortUUIDField(
length=16,
max_length=40,
prefix="id_",
alphabet="abcdefg1234",
primary_key=True,
)
Сиденот:
def getImageURL(self, filename): #Self would normally be defined as instance, but I suppose this is just semantics.
Это происходит потому, что id сохраняется в модели после вызова save()
. Первой догадкой было бы использовать save()
, чтобы получить объект в ответ. Но save() ничего не возвращает. Поэтому я собрал небольшой пример
class Thingy(models.Model):
name = models.CharField(
_('name'),
max_length=64,
)
def save(self, *args, **kwargs):
super(Thingy, self).save(*args, **kwargs)
print(self.pk)
Мой тест был:
>>> t = Thingy(name="lol")
>>> t.save()
1
И он напечатал первичный ключ, так как save()
мутирует self
. Можно проверить, существует ли pk
перед save()
. Если да, просто добавьте путь к изображению. Если нет. Выполните сначала save()
, манипулируйте путем изображения с помощью pk
и снова сохраните объект. Это не слишком элегантно, но, полагаю, это единственный способ.