Использование кэша Django для хранения свойств модели
У меня есть модель изображения с внешним ключом к родительской модели.
class MyImage(models.Model):
parent = models.ForeignKey(ParentModel, related_name='images', on_delete=models.CASCADE)
image = models.ImageField(upload_to='images')
Я также использую django-s3-storage, чтобы эти изображения обслуживались из частного ведра S3.
Когда я запрашиваю url изображения в шаблоне, используя (это детальное представление на основе класса, я также получаю изображения в представлении списка на основе класса):
{% for image in object.images.all %}
<img src="{{image.image.url}}" alt="">
{% endfor %}
значение, возвращаемое из url - это подписанный url, и это нормально. Я бы предпочел не делать свой bucket публичным. Проблема в том, что этот подписанный url генерируется каждый раз, когда я получаю url из модели изображения, что предотвращает кэширование изображения в браузере, поскольку подпись меняется при каждом запросе. Это не идеально, поскольку эти изображения будут редко меняться, и я бы хотел, чтобы они кэшировались в браузере для снижения затрат на S3.
В настоящее время я также использую встроенное кэширование Django (в моем случае я пока использую кэширование базы данных). Встроенное кэширование позволяет мне кэшировать фрагменты шаблонов следующим образом:
{% for image in object.images.all %}
{% cache 1440 object_image object %}
<img src="{{image.image.url}}" alt="">
{% endcache %}
{% endfor %}
Это вроде бы работает нормально, поскольку фрагмент кэшируется с подписанным url; однако я использую изображения в нескольких разных шаблонах, и у меня также есть дополнительная логика, которую я использую для получения изображений на основе других полей модели изображений (default, thumbnail и т.д.). Это означает, что одно изображение будет хранить несколько различных кэшированных значений, каждое из которых будет иметь свой подписанный url. Это не конец света, но я бы хотел, чтобы подписанный url изображения был одинаковым для всех шаблонов.
Читая документацию по кэшированию, не существует встроенного декоратора, который можно было бы использовать для свойства модели и который функционировал бы так же, как тег фрагмента шаблона.
Я хотел бы добавить свойство модели к моей модели изображения, которое оформлено так, чтобы url изображения кэшировалось, чтобы я мог просто вызвать его из любого шаблона, и оно вернет тот же подписанный url из кэша, например:
class MyImage(models.Model):
parent = models.ForeignKey(ParentModel, related_name='images', on_delete=models.CASCADE)
image = models.ImageField(upload_to='images')
@property
@cache('object_image', object)
def url(self):
return self.image.url
Поскольку не похоже, что существует декоратор, это тот случай, когда я должен просто реализовать свой собственный декоратор и/или получить доступ к API кэша непосредственно внутри моего свойства url? Или мне не хватает существующего интерфейса, с помощью которого я могу получить доступ к встроенным функциям и использовать их вместо этого?
from django.core.cache import cache
class MyImage(models.Model):
parent = models.ForeignKey(ParentModel, related_name='images', on_delete=models.CASCADE)
image = models.ImageField(upload_to='images')
@property
def url(self):
return cache.get_or_set(self, self.image.url, 1440)