Asynchronous file upload for Django
Project description
paper-uploads
Асинхронная загрузка файлов для административного интерфейса Django.
Requirements
- Python >= 3.6
- Django >= 2.2
- paper-admin >= 3.0
- variations
Features
- Каждый файл представлен своей моделью, что позволяет
хранить вместе с изображением дополнительные данные.
Например,
alt
иtitle
. - Загрузка файлов происходит асинхронно и начинается сразу, при выборе файла в интерфейсе администратора.
- Поля модели, ссылающиеся на файлы, являются производными
от
OneToOneField
и не используют<input type="file">
. Благодаря этому, при ошибках валидации формы, прикрепленные файлы не сбрасываются. - Загруженные картинки можно нарезать на множество вариаций. Каждая вариация гибко настраивается. Можно указать размеры, качество сжатия, формат, добавить дополнительные pilkit-процессоры, распознавание лиц и другое. См. variations.
- Совместим с django-storages.
- Опциональная интеграция с django-rq для отложенной нарезки картинок на вариации.
- Внутренний подмодуль
paper_uploads.cloudinary
предоставляет поля и классы, реализующие хранение файлов в облаке Cloudinary. - Возможность создавать коллекции файлов. В частности, галерей изображений с возможностью сортировки элементов.
Table of Contents
- Installation
- FileField
- ImageField
- Collections
- Programmatically upload files
- Management Commands
- Validators
- Cloudinary
- Settings
Installation
Install paper-uploads
:
pip install paper-uploads[full]
Add paper_uploads
to INSTALLED_APPS
in settings.py
:
INSTALLED_APPS = [
# ...
'paper_uploads',
# ...
]
Configure paper-uploads
in django's settings.py
:
PAPER_UPLOADS = {
'VARIATION_DEFAULTS': {
'jpeg': dict(
quality=80,
progressive=True,
),
'webp': dict(
quality=75,
)
}
}
# Add JS translations
PAPER_LOCALE_PACKAGES = [
"django.contrib.admin",
"paper_admin",
"paper_uploads",
]
FileField
Поле для загрузки файла.
На загружаемые файлы можно наложить ограничения с помощью валидаторов.
from django.db import models
from django.utils.translation import ugettext_lazy as _
from paper_uploads.models import *
from paper_uploads.validators import *
class Page(models.Model):
report = FileField(_('file'), blank=True, validators=[
SizeValidator(10*1024*1024) # up to 10Mb
])
При загрузке файла создается экземпляр модели UploadedFile
.
UploadedFile
Модель, представляющая загруженный файл.
Поля модели:
Поле | Тип | Описание |
---|---|---|
file | FileField |
Ссылка на файл, хранящийся в Django-хранилище. |
display_name | CharField |
Удобочитаемое название файла для вывода на сайте. Пример: Отчёт за 2019 год . |
basename | CharField |
Имя файла без пути, суффикса и расширения. Пример: my_document . |
extension | CharField |
Расширение файла в нижнем регистре, без точки в начале. Пример: doc . |
size | PositiveIntegerField |
Размер файла в байтах. |
checksum | CharField |
Контрольная сумма файла. Используется для отслеживания изменений файла. |
created_at | DateTimeField |
Дата создания экземпляра модели. |
modified_at | DateTimeField |
Дата изменения модели. |
uploaded_at | DateTimeField |
Дата загрузки файла. |
Свойства модели:
Поле | Тип | Описание |
---|---|---|
name | str |
Полное имя файла, передающееся в Django storage. Пример: files/my_document_19sc2Kj.pdf . |
Для упрощения работы с загруженными файлами, некоторые методы и свойства
стандартного класса FieldFile
проксированы на уровень модели:
open
close
closed
read
seek
tell
readable
writable
seekable
url
path
chunks
Таким образом, вместо page.report.file.url
можно использовать
page.report.url
.
Поддерживается протокол контекстного менеджера:
page = Page.objects.first()
with page.report.open() as fp:
print(fp.read(10))
ImageField
Поле для загрузки изображений.
Во многом аналогично FileField. Может хранить ссылку
как на единственное изображение (подобно стандартному полю
ImageField
), так и на семейство вариаций одного изображения,
созданных из исходного с помощью библиотеки variations.
from django.db import models
from django.utils.translation import ugettext_lazy as _
from paper_uploads.models import *
class Page(models.Model):
image = ImageField(_('single image'), blank=True)
При загрузке изображения создается экземпляр модели UploadedImage
.
UploadedImage
Модель, представляющая загруженное изображение.
Поля модели:
Поле | Тип | Описание |
---|---|---|
file | FileField |
Ссылка на файл, хранящийся в Django-хранилище. |
title | CharField |
Название изображения, которое можно вставить в атрибут title тэга <img> . |
description | CharField |
Описание изображения, которое можно вставить в атрибут alt тэга <img> . |
width | PositiveSmallIntegerField |
Ширина загруженного изображения. |
height | PositiveSmallIntegerField |
Высота загруженного изображения. |
basename | CharField |
Имя файла без пути, суффикса и расширения. Пример: my_image . |
extension | CharField |
Расширение файла в нижнем регистре, без точки в начале. Пример: jpg . |
size | PositiveIntegerField |
Размер файла в байтах. |
checksum | CharField |
Контрольная сумма файла. Используется для отслеживания изменений файла. |
created_at | DateTimeField |
Дата создания экземпляра модели. |
modified_at | DateTimeField |
Дата изменения модели. |
uploaded_at | DateTimeField |
Дата загрузки файла. |
Свойства модели:
Поле | Тип | Описание |
---|---|---|
name | str |
Полное имя файла, передающееся в Django storage. Пример: images/my_image_19sc2Kj.jpg . |
По аналогии с FileField
, модель UploadedImage
проксирует
методы и свойства стандартного класса FieldFile
.
Variations
Вариация - это дополнительное изображение, которое получается из оригинального путём заранее заданных трансформаций.
Вариации описываются словарем variations
поля ImageField
:
from django.db import models
from django.utils.translation import ugettext_lazy as _
from paper_uploads.models import *
class Page(models.Model):
image = ImageField(_('image with variations'),
blank=True,
variations=dict(
desktop=dict(
size=(1600, 0),
clip=False,
jpeg=dict(
quality=80,
progressive=True
),
),
tablet=dict(
size=(1024, 0),
clip=False,
jpeg=dict(
quality=75,
),
),
mobile=dict(
size=(640, 0),
clip=False,
)
)
)
Со списком допустимых опций для вариаций можно ознакомиться в библитеке variations.
К вариациям можно обращаться прямо из экземпляра UploadedImage
:
print(page.image.desktop.url)
Manually creating variation files
Нарезка изображения на вариации происходит при его загрузке. Объявление новых вариаций (равно как изменение существующих) для поля, в которое уже загружен файл, не приведёт к созданию новых файлов.
Для того, чтобы создать файлы для новых вариаций (либо перезаписать существующие вариации, в которые были внесены изменения) можно поступить одним из ниже описанных способов.
-
Вызвать метод
recut()
(либоrecut_async()
) из экземпляраUploadedImage
:page.image.recut()
При вызове этого метода все файлы вариаций для указанного экземпляра создаются заново.
Можно явно указать имена вариаций, которые необходимо перезаписать:page.image.recut(["desktop", "mobile"])
-
Выполнить management-команду
recreate_variations
:python3 manage.py recreate_variations app.page --field=report
Эта команда сгенерирует вариации для всех экземпляров указанной модели.
Using Redis Queue for variation update
Если загрузка изображений происходит достаточно часто и количество вариаций для каждого изображения велико, то процесс создания вариаций может занимать значительное время. Это может оказать негативное влияние на производительность веб-сервера и даже послужить зоной для DoS-атаки.
Для того, чтобы стабилизировать процесс загрузки изображений, рекомендуется создавать вариации асинхронно, в отдельном процессе, с помощью django-rq.
pip install django-rq
# settings.py
PAPER_UPLOADS = {
# ...
"RQ_ENABLED": True,
"RQ_QUEUE_NAME": "default"
}
Теперь при загрузке изображения вместо метода recut()
будет вызываться
метод recut_async()
. При его использовании, превью для админки генерируется
синхронно, а все остальные вариации - через отложенную задачу, которая
помещается в очередь, указанную в опции RQ_QUEUE_NAME
.
Variation versions
Допустим, у нас есть изображение, которое нужно отобразить в трех
вариантах: desktop
, tablet
и mobile
. Если мы хотим поддерживать
дисплеи Retina, нам нужно добавить ещё три вариации для размера 2x
.
Если мы также хотим использовать формат WebP
(сохранив исходный формат
для обратной совместимости), то общее количество вариаций достигает 12.
Поскольку Retina-вариации отличаются от обычных только увеличенным
на постоянный коэффициент размером, а WebP
-вариации — добавлением
параметра format = "webp"
, мы можем создавать эти вариации
автоматически. Это и есть версии вариации.
Перечень версий, которые нужно сгенерировать, указываются в параметре
вариации versions
. Поддерживаются следующие значения:
webp
, 2x
, 3x
, 4x
.
from django.db import models
from django.utils.translation import ugettext_lazy as _
from paper_uploads.models import *
class Page(models.Model):
image = ImageField(_('image'), blank=True,
variations=dict(
desktop=dict(
# ...
versions={'webp', '2x', '3x'}
)
)
)
Приведенный выше код создаст следующие вариации:
desktop
- оригинальная вариацияdesktop_webp
-WebP
-версия оригинальной вариацииdesktop_2x
- Retina 2xdesktop_webp_2x
-WebP
-версия Retina 2xdesktop_3x
- Retina 3xdesktop_webp_3x
-WebP
-версия Retina 3x
NOTE: Retina-суффикс всегда следует после суффикса webp
, если
он есть.
Если необходимо переопределить какие-то параметры дополнительной вариации, то придётся объявлять вариацию явно:
from django.db import models
from django.utils.translation import ugettext_lazy as _
from paper_uploads.models import *
class Page(models.Model):
image = ImageField(_('image'), blank=True,
variations=dict(
desktop=dict(
size=(800, 600),
versions={'webp', '2x', '3x'}
),
desktop_2x=dict(
size=(1600, 1200),
jpeg=dict(
quality=72
)
)
)
)
Collections
Коллекция — это модель, группирующая экземпляры других моделей (элементов коллекции). В частности, с помощью коллекции можно создать фото-галерею или список файлов.
Для создания коллекции необходимо объявить класс, унаследованный
от Collection
и указать модели элементов, которые могут входить
в коллекцию. Созданную коллекцию можно подключить к модели с
помощью CollectionField
:
from django.db import models
from paper_uploads.models import *
# Collection model
class PageFiles(Collection):
svg = CollectionItem(SVGItem)
image = CollectionItem(ImageItem)
file = CollectionItem(FileItem)
# Target model
class Page(models.Model):
files = CollectionField(PageFiles)
Класс Collection
обладает особенным свойством: любой дочерний
класс, унаследованный от Collection
, является proxy-классом для
Collection
.
В большинстве случаев коллекции отличаются друг от друга только набором элементов, которые могут входит в коллекцию. Использование proxy-моделей предотвращает создание для каждой такой коллекции отдельной таблицы в БД.
Как следствие, вы не можете добавлять собственные поля в классы коллеций. Это ограничение можно снять, явно указав, что дочерний класс не должен быть proxy-моделью. В этом случае для коллекции будет создана отдельная таблица в БД.
from django.db import models
from paper_uploads.models import *
class CustomCollection(Collection):
file = CollectionItem(FileItem)
name = models.CharField("name", max_length=128, blank=True)
class Meta:
proxy = False
Collection items
Псевдо-поле CollectionItem
подключает к коллекции модель элемента
под заданным именем. Это имя сохраняется в БД при загрузке файла.
По этой причине не рекомендуется менять имена элементов коллекций,
если в неё уже загружены файлы.
from paper_uploads.models import *
class PageFiles(Collection):
svg = CollectionItem(SVGItem)
image = CollectionItem(ImageItem)
file = CollectionItem(FileItem)
В приведённом примере, коллекция PageFiles
может содержать элементы
трех классов: SVGItem
, ImageItem
и FileItem
. Порядок подключения
элементов коллекции имеет значение: первый класс, чей метод file_supported()
вернет True
, определит модель загруженного файла. По этой причине
FileItem
должен указываться последним, т.к. он принимает любые файлы.
Вместе с моделью элемента, в поле CollectionItem
можно указать
валидаторы:
from paper_uploads.models import *
from paper_uploads.validators import SizeValidator
class FileCollection(Collection):
file = CollectionItem(FileItem, validators=[
SizeValidator(2 * 1000 * 1000)
])
В состав библиотеки входят следующие классы элементов:
ImageItem
. Для хранения изображения с возможностью нарезки на вариации.SVGItem
. Для хранения SVG иконок.FileItem
. Может хранить любой файл.
Вариации для изображений коллекции можно указать двумя способами:
-
в атрибуте класса коллекции
VARIATIONS
:from paper_uploads.models import * class PageGallery(Collection): image = CollectionItem(ImageItem) VARIATIONS = dict( mobile=dict( size=(640, 0), clip=False ) )
-
в дополнительных параметрах поля
CollectionItem
по ключуvariations
:from paper_uploads.models import * class PageGallery(Collection): image = CollectionItem(ImageItem, options={ "variations": dict( mobile=dict( size=(640, 0), clip=False ) ) })
ImageCollection
Для коллекций, предназначенных исключительно для изображений, из коробки
доступна модель для наследования ImageCollection
. К ней уже подключен
класс элементов-изображений.
from paper_uploads.models import *
class PageGallery(ImageCollection):
VARIATIONS = dict(
wide=dict(
size=(1600, 0),
clip=False,
),
desktop=dict(
size=(1280, 0),
clip=False,
),
tablet=dict(
size=(960, 0),
clip=False,
),
mobile=dict(
size=(640, 0),
)
)
Custom collection item classes
В простейших случаях можно использовать прокси-модели на основе существующих моделей.
Например, для того, чтобы хранить файлы определенной галереи в отдельной папке,
можно создать проски модель к ImageItem
:
from paper_uploads.models import *
class ProxyImageItem(ImageItem):
class Meta:
proxy = True
def get_file_folder(self) -> str:
return "custom-images/%Y"
class CustomCollection(Collection):
image = CollectionItem(ProxyImageItem)
Для более сложных случаев (когда требуется отдельная таблица в БД) необходимо
использовать прямое наследование. Но уже не от конкретных моделей (FileItem
,
ImageItem
и т.п.), а от абстрактных. Таких как FileItemBase
, ImageItemBase
или более общих CollectionItemBase
и CollectionFileItemBase
.
from django.db import models
from paper_uploads.models import *
class CustomImageItem(ImageItemBase): # не ImageItem!
caption = models.TextField("caption", blank=True)
class CustomCollection(Collection):
image = CollectionItem(CustomImageItem)
Programmatically upload files
В полях FileField
и ImageField
по умолчанию используются экземпляры
моделей UploadedFile
и UploadedImage
соответственно. Обе модели,
помимо файлового поля, содержат ещё три поля, которые необходимо
заполнить. Эти поля формируют слабую ссылку (weak reference) на поле
модели, с которым связан файл:
owner_app_label
owner_model_name
owner_fieldname
С помощью этих полей можно определить, где используется данный файл.
А management-команда check_uploads
использует данные этих полей,
чтобы обнаружить потенциально неиспользуемые файлы.
Заполнить поля можно вручную, в конструкторе, либо воспользоваться
методом set_owner_from()
.
from django.db import models
from paper_uploads.models import *
class Page(models.Model):
photo = ImageField(_("photo"))
report = FileField(_("report"))
photo = UploadedImage()
photo.set_owner_from(Page._meta.get_field("photo"))
with open("picture.jpg", "rb") as fp:
photo.attach_file(fp)
photo.save()
report = UploadedFile()
report.set_owner_from(Page._meta.get_field("report"))
with open("file.doc", "rb") as fp:
report.attach_file(fp)
report.save()
page = Page.objects.create(
photo=photo,
report=report
)
Такие же поля есть в коллекциях:
from django.db import models
from paper_uploads.models import *
class PageGallery(ImageCollection):
pass
class Page(models.Model):
gallery = CollectionField(PageGallery)
gallery = PageGallery()
gallery.set_owner_from(Page._meta.get_field("gallery"))
gallery.save()
item = ImageItem()
item.attach_to(gallery)
with open("image.jpg", "rb") as fp:
item.attach_file(fp)
item.save()
page = Page.objects.create(
gallery=gallery
)
Management Commands
check_uploads
Запускает комплексную проверку загруженных файлов и выводит результат.
Список производимых тестов:
- загруженный файл существует в файловой системе
- для изображений существуют все файлы вариаций
- модель-владелец (указанная в
owner_app_label
иowner_model_name
) существует - в модели-владельце существует поле
owner_fieldname
- существует единственный экземпляр модели-владельца со ссылкой на файл
- у элементов коллекций указан существующий и допустимый
item_type
- модель элементов коллекций идентична указанной
для
item_type
При указании ключа --fix-missing
все отсутствующие
вариации изображений будут автоматически перенарезаны
из исходников.
python3 manage.py check_uploads --fix-missing
clean_uploads
Находит мусорные записи в БД (например те, у которых нет владельца) и предлагает их удалить.
Владелец загруженного файла устанавливается в момент сохранения страницы
в админке. А это происходит позже фактической загрузки файла на сервер.
Как следствие, в течение некоторого времени файл будет являться "сиротой".
Для того, чтобы такие файлы не удалялись, команда clean_uploads
игнорирует
файлы, загруженные за последние 30 минут. Изменить интервал фильтрации
(в минутах) можно через ключ --min-age
.
python3 manage.py clean_uploads --min-age=60
recreate_variations
Перенарезает вариации для указанных моделей.
Модель указывается в формате app_label.model_name
.
Если модель является коллекцией, необходимо указать параметр --item-type
:
python3 manage.py recreate_variations 'app.Photos' --item-type='image'
Для обычных моделей необходимо указать параметр --field
:
python3 manage.py recreate_variations 'app.Page' --field='image'
По умолчанию перенарезаются все возможные вариации для каждого экземпляра указанной модели. Можно указать конкретные вариации, которые нужно перенарезать:
python3 manage.py recreate_variations 'app.Page' --field='image' --variations big small
remove_variations
Удаление файлов вариаций.
Параметры аналогичны параметрам recreate_variations
.
python3 manage.py remove_variations 'app.Page' --field='image'
Validators
Для добавления ограничений на загружаемые файлы применяются специальные валидаторы:
SizeValidator
- задает максимально допустимый размер файла в байтах.ExtensionValidator
- задает допустимые расширения файлов.MimeTypeValidator
- задает допустимые MIME типы файлов.ImageMinSizeValidator
- устанавливает минимальный размер загружаемых изображений.ImageMaxSizeValidator
- устанавливает максимальный размер загружаемых изображений.
from django.db import models
from django.utils.translation import ugettext_lazy as _
from paper_uploads.models import *
from paper_uploads.validators import *
class Page(models.Model):
image = ImageField(_('image'), blank=True, validators=[
SizeValidator(10 * 1000 * 1000), # max 10Mb
ImageMaxSizeValidator(800, 800) # max dimensions 800x800
])
class PageGallery(Collection):
file = CollectionItem(FileItem, validators=[
SizeValidator(10 * 1000 * 1000),
])
Cloudinary
Во встроенном модуле paper_uploads.cloudinary
находятся поля и классы,
позволяющие загружать файлы и картинки в облачный сервис Cloudinary.
Помимо очевидной выгоды от хранения данных в облаке, использование Cloudinary в качестве хранилища файлов даёт возможность пользоваться API для трансформации изображений и медиа.
Installation
pip install cloudinary
- Добавить
paper_uploads.cloudinary
иcloudinary
вINSTALLED_APPS
.INSTALLED_APPS = [ # ... 'paper_uploads', 'paper_uploads.cloudinary', 'cloudinary', # ... ]
- Задать данные учетной записи Cloudinary
$ export CLOUDINARY_URL=cloudinary://API-Key:API-Secret@Cloud-name?sign_url=1&secure=1
Чтобы предотвратить генерацию трасформаций конечными пользователями, рекомендуется включить в вашем аккаунте Cloudinary Strict transformations.
Model fields
Вместо FileField
и ImageField
используются поля CloudinaryFileField
,
CloudinaryImageField
и CloudinaryMediaField
.
from django.db import models
from paper_uploads.cloudinary.models import *
class Page(models.Model):
file = CloudinaryFileField(_('file'), blank=True)
image = CloudinaryImageField(_('image'), blank=True)
media = CloudinaryMediaField(_('media'), blank=True)
Дополнительные параметры загрузки Cloudinary
можно задать с помощью параметра cloudinary
:
from django.db import models
from paper_uploads.cloudinary.models import *
class Page(models.Model):
file = CloudinaryFileField(_('file'), blank=True, cloudinary={
"use_filename": False
})
Collections
Для коллекций используется тот же класс Collection
, что используется
при локальном хранении файлов. Отличаются только классы элементов коллекций.
В состав библиотеки входит три класса элементов коллекции:
CloudinaryFileItem
, CloudinaryImageItem
и CloudinaryMediaItem
(для аудио и видео).
from django.db import models
from paper_uploads.models import *
from paper_uploads.cloudinary.models import *
class PageFiles(Collection):
image = CollectionItem(CloudinaryImageItem)
file = CollectionItem(CloudinaryFileItem)
class Page(models.Model):
files = CollectionField(PageFiles)
Также, как и для обычных коллекций, для Cloudinary объявлена готовая
коллекция для изображений — CloudinaryImageCollection
:
from django.db import models
from paper_uploads.models import *
from paper_uploads.cloudinary.models import *
class PageGallery(CloudinaryImageCollection):
pass
class Page(models.Model):
gallery = CollectionField(PageGallery)
Usage
Для вывода ссылки на файл, загруженный в Cloudinary, библиотека содержит
шаблонный тэг paper_cloudinary_url
:
{% load paper_cloudinary %}
<img src={% paper_cloudinary_url page.image width=1024 crop=fill %}>
Для jinja2
:
<img src={% paper_cloudinary_url page.image, width=1024, crop=fill %}>
Также, для jinja2
доступна одноименная глобальная функция:
<img src={{ paper_cloudinary_url(page.image, width=1024, crop='fill') }}>
Customize upload folder
По умолчанию, папки для загружаемых файлов задаются глобально, в настройках:
PAPER_UPLOADS = {
# ...
"FILES_UPLOAD_TO": "files/%Y-%m-%d",
"IMAGES_UPLOAD_TO": "images/%Y-%m-%d",
"COLLECTION_FILES_UPLOAD_TO": "collections/files/%Y-%m-%d",
"COLLECTION_IMAGES_UPLOAD_TO": "collections/images/%Y-%m-%d",
}
Для того, чтобы загружаемые файлы помещались в отдельную папку для конкретного
поля, необходимо переопределить метод get_file_folder
:
from django.db import models
from paper_uploads.models import *
class CustomUploadedFile(UploadedFile):
class Meta:
proxy = True
def get_file_folder(self) -> str:
return "custom-files/%Y-%m-%d"
class Page(models.Model):
file = FileField(_("file"), to=CustomUploadedFile)
Settings
Все настройки указываются в словаре PAPER_UPLOADS
.
PAPER_UPLOADS = {
'STORAGE': 'django.core.files.storage.FileSystemStorage',
'STORAGE_OPTIONS': {},
'RQ_ENABLED': True,
'VARIATION_DEFAULTS': {
'jpeg': dict(
quality=80,
progressive=True,
),
'webp': dict(
quality=75,
)
}
}
STORAGE
Путь к классу хранилища Django.
Значение по умолчанию: django.core.files.storage.FileSystemStorage
STORAGE_OPTIONS
Параметры инициализации хранилища.
Значение по умолчанию: {}
FILES_UPLOAD_TO
Путь к папке, в которую загружаются файлы из FileField. Может содержать параметры для даты и времени (см. upload_to).
Значение по умолчанию: files/%Y-%m-%d
IMAGES_UPLOAD_TO
Путь к папке, в которую загружаются файлы из ImageField.
Значение по умолчанию: images/%Y-%m-%d
COLLECTION_FILES_UPLOAD_TO
Путь к папке, в которую загружаются файлы коллекций.
Значение по умолчанию: collections/files/%Y-%m-%d
COLLECTION_IMAGES_UPLOAD_TO
Путь к папке, в которую загружаются изображения коллекций.
Значение по умолчанию: collections/images/%Y-%m-%d
COLLECTION_ITEM_PREVIEW_WIDTH
, COLLECTION_ITEM_PREVIEW_HEIGTH
Размеры превью элементов коллекций в админке.
Значение по умолчанию: 180
x 135
COLLECTION_IMAGE_ITEM_PREVIEW_VARIATIONS
Вариации, добавляемые к каждому классу изображений коллекций
для отображения превью в админке. Размеры файлов должны
совпадать с COLLECTION_ITEM_PREVIEW_WIDTH
и
COLLECTION_ITEM_PREVIEW_HEIGTH
.
RQ_ENABLED
Включает нарезку картинок на вариации через отложенные задачи. Требует наличие установленного пакета django-rq.
Значение по умолчанию: False
RQ_QUEUE_NAME
Название очереди, в которую помещаются задачи по нарезке картинок.
Значение по умолчанию: default
VARIATION_DEFAULTS
Параметры вариаций по умолчанию.
Параметры, указанные в этом словаре, будут применены к каждой вариации, если только вариация их явно не переопределяет.
Значение по умолчанию: None
CLOUDINARY_TYPE
Тип загрузки файлов. Возможные значения: private
, upload
.
Значение по умолчанию: private
CLOUDINARY_TEMP_DIR
Папка в разделе /tmp/
, в которую скачиваются файлы из Cloudinary
при чтении их содержимого. Доступ к содержимому большого количества
файлов из Cloudinary может привести к скачиванию больших объемов данных
и захламлению временной папки.
CLOUDINARY_UPLOADER_OPTIONS
Словарь, задающий глобальные параметры загрузки для Cloudinary.
Значение по умолчанию:
PAPER_UPLOADS = {
"CLOUDINARY_UPLOADER_OPTIONS": {
"use_filename": True,
"unique_filename": True,
"overwrite": True,
"invalidate": True
}
}
Development and Testing
After cloning the Git repository, you should install this in a virtualenv and set up for development:
virtualenv .venv
source .venv/bin/activate
pip install -r ./requirements.txt
pre-commit install
Install npm
dependencies and build static files:
npm ci
npx webpack
Create .env
file:
CLOUDINARY_URL=cloudinary://XXXXXXXXXXXXXXX:YYYYYYYYYYYYYYYYYYYYYYYYYYY@ZZZZZZ?sign_url=1&secure=1
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for paper_uploads-0.7.0-py2.py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 660cd296efad76491d19881d7858214cd4d9d7222aa6a336f820fd2636fbb35d |
|
MD5 | 5f1cfdbb78701d722a57d5b11210f688 |
|
BLAKE2b-256 | 91b9f84635ec92836ae616374513b1101597b7f5006851b1ad67cb8c9e1772e8 |