Social Profiles

My Projects

Django Framework - как сохранять изображения

Крайне не рекомендую использовать Django ORM для этого, но все же...

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

Я использую следующий вариант решения: имя файла картинки это хэш (sha1) который вычисляется от url картинки, от этого хэша откусываются 2 первых и 2 последующих символа, которые будут являться названием директорий.

Например, если хэш был

537a1d5139ea13ecd3f1558d513bed2fdbc38478

то картинка будет сохраняться сюда

/53/7a/537a1d5139ea13ecd3f1558d513bed2fdbc38478.jpg

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

Реализация для Django (код из живого проекта), используем тот факт, что в качесте upload_to может выступ не только строка но и функция которая эту строку будет генерировать:

def get_clinic_image_path(instance, filename):
    hashname = sha1(filename).hexdigest() + '.jpg'
    return os.path.join('clinic', hashname[:2], hashname[2:4],
                        hashname)

class Clinic(SeoMixin):
    title = models.CharField(max_length=255, db_index=True)

    teaser = models.TextField(blank=True)
    description = RichTextField(blank=True)

    # сохраняем картинку
    image = models.ImageField(blank=True, upload_to=get_clinic_image_path)

Еще один вариант, это наследовать CustomImageField от ImageField и там описать свою логику, тоже имеет право на жизнь, но займет гораздо больше времени на реализацию. Подробнее - в документации Django по Custom model fields

Произвольное количество изображений

Если каждомй отдельной записи в БД может соответствовать произвольное кол-во картинок, то придется создвать отдельную таблицу с линком (реляцией).

class Images(models.Model):
    alt = models.CharField(max_length=64, blank=True)
    src = models.ImageField(upload_to=get_item_image_path)
    # и собственно линк на Item
    item = models.ForeignKey('Item', null=True, blank=True, related_name='images')

class Item(models.Model):
    title = models.CharField(max_length=128, db_index=True)

Не слишком сложно.

comments powered by Disqus