sorl-thumbnail не удалит миниатюры - PullRequest
3 голосов
/ 22 февраля 2011

Проблемы с SORL Thumbnail и удалением файлов миниатюр или обновлением миниатюр, когда файл перезаписан.Сценарий таков, что у меня есть файл, который для каждой записи всегда одинаков, но может быть перезаписан.Нужно воссоздать миниатюру, когда новый файл загружен, а старый файл перезаписан.

Это на уровне модели + формы, поэтому я использую низкоуровневый API для создания больших пальцев.

Пробовал использовать:

from sorl.thumbnail import delete

delete(filename)

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

Я даже пытался:

from sorl.thumbnail.images import ImageFile
from sorl.thumbnail import default

image_file = ImageFile(filename)
default.kvstore.delete_thumbnails(image_file)

Снова сбезуспешно.

Пожалуйста, помогите!

Обновление:

Я нашел обходной путь, создав альтернативный ThumbnailBackend и новый метод _get_thumbnail_filename.Новый метод использует хеш файла SHA-1, чтобы всегда иметь миниатюру, характерную для текущего файла.

Вот серверная часть для всех, кто может столкнуться с подобным сценарием.

class HashThumbnailBackend(ThumbnailBackend):

  def _get_thumbnail_filename(self, source, geometry_string, options):
    """
    Computes the destination filename.
    """
    import hashlib

    # hash object
    hash = hashlib.sha1()

    # open file and read it in as chunks to save memory
    f = source.storage.open(u'%s' % source, 'rb')
    while True:
      chunk = f.read(128)
      if not chunk:
        break
      hash.update(hashlib.sha1(chunk).hexdigest())

    # close file
    f.close()

    hash.update(geometry_string)
    hash.update(serialize(options))
    key = hash.hexdigest()

    # make some subdirs
    path = '%s/%s/%s' % (key[:2], key[2:4], key)
    return '%s%s.%s' % (settings.THUMBNAIL_PREFIX, path,
                        self.extensions[options['format']])

Ответы [ 4 ]

16 голосов
/ 23 февраля 2011

Это немного сложно объяснить, поэтому я сделал эту потрясающую таблицу. команды первого столбца перечислены ниже, остальные столбцы отмечают, когда он удаляется с помощью X. Оригинал - это исходный файл, миниатюры миниатюр для оригинала, а KV - ссылка на хранилище значений ключа.

| Command | Original | Thumbnails | KV Original | KV Thumbnails |
| #1      | X        | X          | X           | X             |
| #2      |          | X          |             | X             |
| #3      |          | X          | X           | X             |
  1. sorl.thumbnail.delete(filename)
  2. sorl.thumbnail.default.kvstore.delete_thumbnails(image_file)
  3. sorl.thumbnail.delete(filename, delete_file=False)

Насколько я понимаю, вы действительно хотите сделать # 3. Теперь ваша проблема ... предположение состоит в том, что filename не ссылается на имя файла относительно MEDIA_ROOT (если вы используете другой бэкэнд хранилища, ситуация будет аналогичной). Но я думаю, что мне нужно знать, что вы делаете, кроме этого, чтобы получить лучшую картинку, обратите внимание, что ImageFields и FileFields не перезаписывают, также обратите внимание, что django изменил поведение удаления в 1.2.5, см. Примечания к выпуску.

Обновление: Любой, кто читает это, должен заметить, что вышеупомянутый способ создания миниатюр имен файлов крайне неэффективен , пожалуйста, не используйте его, если вам небезразлично что-либо с производительностью.

6 голосов
/ 16 ноября 2012

Я не совсем уверен, отвечает ли это на ваш вопрос, но у меня была та же проблема, и это было мое решение.

У меня есть модель с FileField, например:

material = models.FileField(upload_to='materials')

При обработке загруженного файла я использую get_thumbnail () для генерации миниатюры, передавая FileField как параметр против файла уровня python позади него.то есть:

thumb = get_thumbnail(modelinstance.material, '%dx%d' % (thumb_width, thumb_height))

Как и в случае с вашей проблемой, я также обнаружил, что если файл имеет такое же имя, sorl будет просто извлекать миниатюру из кэша, а не создавать новую.Отягчающие!

То, что работало, использовало метод удаления sorl и передавал FileField.Сначала я попытался передать файл python за объектом FileField, что, возможно, вы пытались сделать?Исходя из этого:

sorl.thumbnail.delete(modelinstance.material.file)

К этому:

sorl.thumbnail.delete(modelinstance.material)

Казалось бы, выровнялись с хранилищем sorl-thumbnail в KV, и должным образом убрали бы кэшированные миниатюры, чтобы новыйодин может быть создан из нового файла.Yay!

Это было полезно для меня: http://sorl -thumbnail.readthedocs.org / en / latest / operation.html

Кроме того, даже после запуска ./Очистить миниатюры manage.py и очистить миниатюры ./manage.py я не смог заставить Джанго перестать искать старые миниатюры в одном месте.Мне пришлось вручную очистить кеш Django (я использую memcached).Вот как вы можете это сделать:

import os

# Set the DJANGO_SETTINGS_MODULE environment variable.
os.environ['DJANGO_SETTINGS_MODULE'] = "yourproject.settings"

from django.core.cache import cache

# Flush!
cache._cache.flush_all()

Это мой первый ТАК ответ.Надеюсь, это кому-нибудь поможет :) 1027 *

1 голос
/ 05 сентября 2014

Я видел эту проблему. Это происходило потому, что Sorl использовался странно.

Все миниатюры были получены в следующем стиле:

sorl.thumbnail.get_thumbnail(self.picture.url, geometry_string, **options)
# picture being a FieldFile

А при удалении миниатюры (удаляя их из кеша) это делалось так:

sorl.thumbnail.delete(self.picture.name, delete_files=False)

Вскоре мы использовали URL-адрес изображения для создания и извлечения миниатюр, а при удалении мы использовали имя изображения . Хотя Sorl не жаловался на это, KV Store и FS никогда не очищались.

Исправлено было просто изменить имя аргумента get_thumbnail на self.picture.name.

1 голос
/ 26 апреля 2013

Дело в том, что вы не можете использовать ярлык delete(file) с классом файлов, который отличается от класса, который вы использовали для создания этого самого эскиза с помощью get_thumbnail() или {% thumbnail ...%} шаблона тега.

Причина в том, что экземпляры ImageFile, созданные из файловых объектов, получат разные ключи (ImageFile.key), а delete () никогда не сможет извлечь удаляемые эскизы, поскольку ключи не совпадают.

Я не уверен, что это не будет работать, если вы используете объект Python File, а затем, например, объект Django File, но в Django, если вы генерируете миниатюру с объектом FileField и попытайтесь удалить его (и его эскизы) с экземпляром File, он точно не будет работать.

Итак, в ваших шаблонах не делайте:

{% load thumbnail %}
{% thumbnail image "100" as im %}
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}">
{% endthumbnail %}

Где image - это экземпляр models.ImageField, но используйте его атрибут file:

{% load thumbnail %}
{% thumbnail image.file "100" as im %}

И удалить его в своем коде Python (ниже приведен пример хранилища для перезаписи существующего файла, если имя совпадает):

from django.core.files.storage import FileSystemStorage
from django.core.files import File
from sorl.thumbnail import delete


class OverwriteStorage(FileSystemStorage):
    def _save(self, name, content):
        if self.exists(name):
            img = File(open(os.path.join(self.location, name), "w"))
            delete(img)
        return super(OverwriteStorage, self)._save(name, content)

Не уверен, что это ошибка в sorl или есть веская причина для генерации разных ключей.

...