Изменение размеров изображения с django?

Скажите, что Вы имеете файл в наличии в:

/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, и т.д. файл не изменился), в то время как в режиме развертывания я установил заголовки, в которых говорится "кэш навсегда".

12
задан littlejim84 22 July 2009 в 12:32
поделиться

8 ответов

Если вас устраивает, есть готовое приложение Django, которое делает именно то, что вы хотите: https://github.com/sorl/sorl-thumbnail

7
ответ дан 2 December 2019 в 06:26
поделиться

Это то, что я использую в своих моделях для сохранения новый эскиз, если загруженное изображение изменилось. Он основан на другом 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   
4
ответ дан 2 December 2019 в 06:26
поделиться

Ключевой вопрос: когда должен эскиз быть сгенерировано?

  1. Динамически, когда пользователь запрашивает миниатюрное изображение?
  2. Или вы хотите создать файл на физическом диске всякий раз, когда страна вставляется / обновляется в базе данных.

Если (1) я предлагаю вам создать представление, которое соответствует URL-адресу / flagthumbnail / countryid . Затем метод просмотра должен:

  1. Получить экземпляр страны из базы данных
  2. Считать изображение флага в изображение PIL и изменить его размер.
  3. Создать (и вернуть) HTTPResponse с правильным типом содержимого и записать изображение PIL для ответа.

Всякий раз, когда вам нужно отобразить флаг эскиза, просто используйте .

If (2),

2
ответ дан 2 December 2019 в 06:26
поделиться

Думаю, это зависит от того, как и когда вы используете свои эскизы.

Если вы хотите создавать несколько эскизов каждый раз при сохранении страны, вы можете сделать это следующим образом:

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). Вы создаете шаблонный тег, который принимает изображение и размер, а затем создаете и сохраняете изображение соответствующего размера, если вам нужно, или отображаете ранее созданное, если оно есть. Работает неплохо.

2
ответ дан 2 December 2019 в 06:26
поделиться

Переопределение метода сохранения - хороший вариант, но в этом случае я бы более склонен использовать сигнал . Сигналы 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)
2
ответ дан 2 December 2019 в 06:26
поделиться

Райан правильные сигналы - лучший способ пойти, однако преимущество переопределенного сохранения состоит в том, что мы можем получить старый и новый пути изображения, посмотреть, изменилось ли изображение (и если оно создайте новую миниатюру), сохраните экземпляр модели, а затем удалите старое изображение и миниатюру.

Помните, что django не очищает старые изображения за вас, поэтому, если у вас нет сценария для проверки того, что изображения / миниатюры все еще используются и очистите все, что не приведет к утечке дискового пространства. (Это может быть или не быть проблемой для вас в зависимости от размера изображения и частоты обновлений)

Я не уверен, как вы могли бы сделать это с помощью сигнала post_save, и я недостаточно знаю о сигналах (Это исследование на сегодня!), чтобы узнать, есть ли подходящий сигнал pre_save. Если найду, то я

2
ответ дан 2 December 2019 в 06:26
поделиться

Не уверен насчет отправленного вами кода, потому что я никогда не использую модели как таковые, но есть другой метод.

Вы можете реализовать свой собственный FileUploadHandler для обработки изображений загрузка файлов. Пример здесь . Сразу после строки 37 ( dest.close () ) используйте функцию thumbnail (upload_dir + upload.name) (тот, который вы отправили).

Надеюсь, это поможет вам.

2
ответ дан 2 December 2019 в 06:26
поделиться

Я также клянусь, что django-photologue Джастина Дрисколла отлично подходит для изменения размера. Это:

  1. Изменяет размер (то есть можно пропорционально масштабировать до высоты или ширины)
  2. Обрезка (вроде разумно: от центра, вверх, слева, снизу или справа)
  3. При желании увеличенное изображение
  4. Можно добавить эффектов (таких как «цвет», «яркость», «контраст» и «резкость», а также фильтры, такие как «Найти края» и «Тиснение». ваши изображения. Сделайте ваши эскизы черно-белыми.)
  5. Можно добавить простой водяной знак
  6. Кэшировать результаты

В целом это круто.

0
ответ дан 2 December 2019 в 06:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: