Скажите, что Вы имеете файл в наличии в:
/styles/screen.css
Ваш может или добавить параметр запроса с информацией о версии на URI, например:
/styles/screen.css?v=1234
или можно предварительно ожидать информацию о версии, например:
/v/1234/styles/screen.css
, по моему скромному мнению, второй метод лучше для файлов CSS, потому что они могут обратиться к изображениям с помощью относительных URL, что означает это, если Вы определяете background-image
как так:
body {
background-image: url('images/happy.gif');
}
его URL эффективно будет:
/v/1234/styles/images/happy.gif
Это означает, что, если Вы обновляете номер версии, использовал сервер, будет рассматривать это как новый ресурс и не использовать кэшированную версию. Если Вы основываете свой номер версии на Подрывной деятельности/CVS/и т.д. пересмотр это означает, что будут замечены изменения в изображениях, на которые ссылаются в файлах CSS. Это не гарантируется с первой схемой, т.е. URL images/happy.gif
относительно /styles/screen.css?v=1235
/styles/images/happy.gif
, который не содержит информации о версии.
я реализовал кэширующееся решение с помощью этой техники с сервлетами Java и просто обрабатываю запросы к /v/*
с сервлетом, который делегирует к базовому ресурсу (т.е. /styles/screen.css
). В режиме разработки я установил кэширующиеся заголовки, которые говорят клиенту всегда проверять свежесть ресурса с сервером (это обычно приводит к 304, если Вы делегируете к Tomcat DefaultServlet
и .css
, .js
, и т.д. файл не изменился), в то время как в режиме развертывания я установил заголовки, в которых говорится "кэш навсегда".
Если вас устраивает, есть готовое приложение Django, которое делает именно то, что вы хотите: https://github.com/sorl/sorl-thumbnail
Это то, что я использую в своих моделях для сохранения новый эскиз, если загруженное изображение изменилось. Он основан на другом DjangoSnippet, но я не могу вспомнить, кто написал оригинал - если вы знаете, добавьте комментарий, чтобы я мог им указать.
from PIL import Image
from django.db import models
from django.contrib.auth.models import User
import os
import settings
class Photo_Ex(models.Model):
user = models.ForeignKey(User, blank=True, null=True)
photo = models.ImageField(upload_to='photos')
thumbnail = models.ImageField(upload_to='profile_thumb', blank=True,
null=True, editable=False)
def save(self, *args, **kwargs):
size = (256,256)
if not self.id and not self.photo:
return
try:
old_obj = Photo_Ex.objects.get(pk=self.pk)
old_path = old_obj.photo.path
except:
pass
thumb_update = False
if self.thumbnail:
try:
statinfo1 = os.stat(self.photo.path)
statinfo2 = os.stat(self.thumbnail.path)
if statinfo1 > statinfo2:
thumb_update = True
except:
thumb_update = True
pw = self.photo.width
ph = self.photo.height
nw = size[0]
nh = size[1]
if self.photo and not self.thumbnail or thumb_update:
# only do this if the image needs resizing
if (pw, ph) != (nw, nh):
filename = str(self.photo.path)
image = Image.open(filename)
pr = float(pw) / float(ph)
nr = float(nw) / float(nh)
if image.mode not in ('L', 'RGB'):
image = image.convert('RGB')
if pr > nr:
# photo aspect is wider than destination ratio
tw = int(round(nh * pr))
image = image.resize((tw, nh), Image.ANTIALIAS)
l = int(round(( tw - nw ) / 2.0))
image = image.crop((l, 0, l + nw, nh))
elif pr < nr:
# photo aspect is taller than destination ratio
th = int(round(nw / pr))
image = image.resize((nw, th), Image.ANTIALIAS)
t = int(round(( th - nh ) / 2.0))
image = image.crop((0, t, nw, t + nh))
else:
# photo aspect matches the destination ratio
image = image.resize(size, Image.ANTIALIAS)
image.save(self.get_thumbnail_path())
(a, b) = os.path.split(self.photo.name)
self.thumbnail = a + '/thumbs/' + b
super(Photo_Ex, self).save()
try:
os.remove(old_path)
os.remove(self.get_old_thumbnail_path(old_path))
except:
pass
def get_thumbnail_path(self):
(head, tail) = os.path.split(self.photo.path)
if not os.path.isdir(head + '/thumbs'):
os.mkdir(head + '/thumbs')
return head + '/thumbs/' + tail
def get_old_thumbnail_path(self, old_photo_path):
(head, tail) = os.path.split(old_photo_path)
return head + '/thumbs/' + tail
Ключевой вопрос: когда должен эскиз быть сгенерировано?
Если (1) я предлагаю вам создать представление, которое соответствует URL-адресу / flagthumbnail / countryid
. Затем метод просмотра должен:
Всякий раз, когда вам нужно отобразить флаг эскиза, просто используйте
.
If (2),
Думаю, это зависит от того, как и когда вы используете свои эскизы.
Если вы хотите создавать несколько эскизов каждый раз при сохранении страны, вы можете сделать это следующим образом:
from django.db import models
# This is to list all the countries
# For starters though, this will be just United Kingdom (GB)
class Country(models.Model):
name = models.CharField(max_length=120, help_text="Full name of country")
code = models.CharField(max_length=2, help_text="This is the ISO 3166 2-letter country code (see: http://www.theodora.com/country_digraphs.html)")
flag = models.ImageField(upload_to="images/uploaded/country/", max_length=150, help_text="The flag image of the country.", blank=True)
class Meta:
verbose_name_plural = "Countries"
def __unicode__(self):
return self.name
def save(self, force_insert=False, force_update=False):
resize_image(self.flag)
super(Country, self).save(force_insert, force_update)
Если вы не уверены на 100%, какие размеры вам понадобятся, вы можете изменить их размер в последнюю минуту. Я видел, как это эффективно делается с помощью тега шаблона (я верю в версию на Pinax). Вы создаете шаблонный тег, который принимает изображение и размер, а затем создаете и сохраняете изображение соответствующего размера, если вам нужно, или отображаете ранее созданное, если оно есть. Работает неплохо.
Переопределение метода сохранения - хороший вариант, но в этом случае я бы более склонен использовать сигнал . Сигналы Django позволяют «прослушивать» различные события данного типа модели; в этом случае вас заинтересует событие post_save
.
Обычно я подписываюсь на такие сигналы в моем файле models.py
. Ваш код будет выглядеть примерно так:
from django.db.models.signals import post_save
from models import Country
def resize_image(sender, **kwargs):
country = kwargs["instance"]
resize_image(country.flag) # where resize_image generates a thumbnail given a Country instance
post_save.connect(resize_image, sender=Country)
Райан правильные сигналы - лучший способ пойти, однако преимущество переопределенного сохранения состоит в том, что мы можем получить старый и новый пути изображения, посмотреть, изменилось ли изображение (и если оно создайте новую миниатюру), сохраните экземпляр модели, а затем удалите старое изображение и миниатюру.
Помните, что django не очищает старые изображения за вас, поэтому, если у вас нет сценария для проверки того, что изображения / миниатюры все еще используются и очистите все, что не приведет к утечке дискового пространства. (Это может быть или не быть проблемой для вас в зависимости от размера изображения и частоты обновлений)
Я не уверен, как вы могли бы сделать это с помощью сигнала post_save, и я недостаточно знаю о сигналах (Это исследование на сегодня!), чтобы узнать, есть ли подходящий сигнал pre_save. Если найду, то я
Не уверен насчет отправленного вами кода, потому что я никогда не использую модели как таковые, но есть другой метод.
Вы можете реализовать свой собственный FileUploadHandler
для обработки изображений загрузка файлов. Пример
здесь .
Сразу после строки 37 ( dest.close ()
) используйте функцию thumbnail (upload_dir + upload.name)
(тот, который вы отправили).
Надеюсь, это поможет вам.
Я также клянусь, что django-photologue Джастина Дрисколла отлично подходит для изменения размера. Это:
В целом это круто.