pax_global_header 0000666 0000000 0000000 00000000064 14507342020 0014507 g ustar 00root root 0000000 0000000 52 comment=16dcfc8395bb0cb96289a21f5c2ca719db1e5852
sorl-thumbnail-12.10.0/ 0000775 0000000 0000000 00000000000 14507342020 0014610 5 ustar 00root root 0000000 0000000 sorl-thumbnail-12.10.0/.editorconfig 0000664 0000000 0000000 00000000653 14507342020 0017271 0 ustar 00root root 0000000 0000000 ; This file is for unifying the coding style for different editors and IDEs.
; More information at https://EditorConfig.org
root = true
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
[*.py]
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 4
[*.rst]
trim_trailing_whitespace = false
[Makefile]
indent_style = tab
[*.yml]
indent_style = space
indent_size = 2
sorl-thumbnail-12.10.0/.github/ 0000775 0000000 0000000 00000000000 14507342020 0016150 5 ustar 00root root 0000000 0000000 sorl-thumbnail-12.10.0/.github/workflows/ 0000775 0000000 0000000 00000000000 14507342020 0020205 5 ustar 00root root 0000000 0000000 sorl-thumbnail-12.10.0/.github/workflows/release.yml 0000664 0000000 0000000 00000002523 14507342020 0022352 0 ustar 00root root 0000000 0000000 name: Release
on:
push:
branches:
- master
release:
types:
- published
jobs:
build:
if: github.repository == 'jazzband/sorl-thumbnail'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Get pip cache dir
id: pip-cache
run: |
echo "::set-output name=dir::$(pip cache dir)"
- name: Cache
uses: actions/cache@v2
with:
path: ${{ steps.pip-cache.outputs.dir }}
key: release-${{ hashFiles('**/setup.py') }}
restore-keys: |
release-
- name: Install dependencies
run: |
python -m pip install -U pip
python -m pip install -U setuptools twine wheel
- name: Build package
run: |
python setup.py --version
python setup.py sdist --format=gztar bdist_wheel
twine check dist/*
- name: Upload packages to Jazzband
if: github.event.action == 'published'
uses: pypa/gh-action-pypi-publish@master
with:
user: jazzband
password: ${{ secrets.JAZZBAND_RELEASE_KEY }}
repository_url: https://jazzband.co/projects/sorl-thumbnail/upload
sorl-thumbnail-12.10.0/.github/workflows/test.yml 0000664 0000000 0000000 00000002765 14507342020 0021721 0 ustar 00root root 0000000 0000000 name: Test
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11']
target: [pil, imagemagick, graphicsmagick, redis, wand, dbm]
include:
- python-version: '3.8'
target: 'qa'
steps:
- uses: actions/checkout@v3
- name: Start Redis
uses: supercharge/redis-github-action@1.5.0
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install libgraphicsmagick1-dev graphicsmagick libjpeg62 zlib1g-dev
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Get pip cache dir
id: pip-cache
run: |
echo "::set-output name=dir::$(pip cache dir)"
- name: Cache
uses: actions/cache@v3
with:
path: ${{ steps.pip-cache.outputs.dir }}
key:
test-${{ matrix.python-version }}-v1-${{ hashFiles('**/setup.py') }}
restore-keys: |
test-${{ matrix.python-version }}-v1-
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install --upgrade tox tox-gh-actions
- name: Tox tests
run: |
tox -v
env:
TARGET: ${{ matrix.target }}
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
name: Python ${{ matrix.python-version }}
sorl-thumbnail-12.10.0/.gitignore 0000664 0000000 0000000 00000001246 14507342020 0016603 0 ustar 00root root 0000000 0000000 # Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
# Distribution / packaging
env/
bin/
build/
develop-eggs/
dist/
eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
*.egg
.eggs
.installed.cfg
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Translations
*.mo
# Related to Desktops and OS
.DS_Store
.AppleDouble
.LSOverride
._*
.~
.bak
*.swp
*.swo
*.swn
# VCS and DVCS
.svn
# Common IDE's
.idea
.project
.pydevproject
.ropeproject
# Sphinx documentation
docs/_build/
# Virtualenv
.python-version
.env/
# dbm stuff
tests/thumbnail_kvstore
tests/thumbnail_kvstore.db
tests/thumbnail_kvstore.lock
# test related
.coverage
.tox
htmlcov/
coverage.xml
sorl-thumbnail-12.10.0/.pre-commit-config.yaml 0000664 0000000 0000000 00000000136 14507342020 0021071 0 ustar 00root root 0000000 0000000 repos:
- repo: https://github.com/PyCQA/flake8
rev: 6.1.0
hooks:
- id: flake8
sorl-thumbnail-12.10.0/AUTHORS.rst 0000664 0000000 0000000 00000000116 14507342020 0016465 0 ustar 00root root 0000000 0000000 Take a look at https://github.com/jazzband/sorl-thumbnail/graphs/contributors
sorl-thumbnail-12.10.0/CHANGES.rst 0000664 0000000 0000000 00000007103 14507342020 0016413 0 ustar 00root root 0000000 0000000 =======
Changes
=======
12.10.0
=======
* Fixed safe_filter application on various thumbnail template tags.
* Fixed slow performance with external storages like S3.
* Added support for Django 4.2.
* Drop support for Python 3.7.
* Confirmed Python 3.11 support.
12.9.0
======
* Drop support for Django 2.2 and 3.1.
* Added support for Django 4.1.
* Drop support for Python 3.6.
* Fixed various Pillow deprecation warnings.
12.8.0
======
* Drop support for Django 3.0.
* Added support for Django 3.2 and 4.0.
* Confirmed Python 3.9 and 3.10 support.
* Adapted size regex getting size from the identify output. #532
* Display possible ``thumbnail`` command labels in command help.
* Added Jazzband code of conduct.
12.7.0
======
* Drop support for Django 1.11
* Added support for Django 3.1
* Moved to GitHub Action for continuous integration.
* Correction in convert_engine with unknown exif orientation
* Using more resilient _get_exif_orientation logic in convert engine
* Update wand_engine.py for ImageMagick 7
* Fix cannot write mode RGBA as JPEG when thumbnailing a GIF
12.6.3
======
* Deprecate Python 2 compatibility shims in favor of Python 3 only codebase. #623
* Fix README on notes about ImageField cleaning up references on delete. #624
* Fix image ratios with EXIF orientation. #619
* Fix test coverage tracking. #622 and #617
12.6.2
======
* Fix rST syntax errors from 12.6.0 and 12.6.1 that blocked release. #613
* Improve QA setup and add rST validation to Travis and tox test matrix. #613
12.6.1
======
* Deprecate explicit support for Python 3.4 and 3.5 in order to simplify the test matrix #610
* Add requirement for ``setuptools_scm`` to automatically resolve version from git tags #610
* Removed property ``thumbnail.__version__`` #610
12.6.0
======
* Add Cropbox feature in Wand/Convert Engine
* Add testing for Django 2.2
* Remove "django.utils.six" to support Django 3.0+
* Remove Python 2 support
12.5.0
======
* Make the template tag accept a falsey image
* Update identify (of convert_engine) for faster multi-page PDF thumbnailing
* Fix Redis KVStore timeout
* Fix format conversion in Wand engine
* Added setting THUMBNAIL_REMOVE_URL_ARGS
* Add testing for Django 2.1
* Drop support for Django < 1.11
* Added ssl parameter to Redis object instantiation
* Fix 2 ResourceWarning: unclosed file, in tests
* Fix AdminImageWidget with Django 2.1
* Test in release version of Python 3.7
* Remove unused unittest imports in thumbnail_tests.compat
* Add a __str__ method to ImageFile
12.4.1
======
sorl-thumbnail was welcomed into the `Jazzband organization and project
`__. Jazzband is open to all, and any member of Jazzband
can contribute directly to sorl-thumbnail's GitHub repo. We hope this will
encourage more open source programmers to contribute. Thank you @mariocesar for
taking this step and for the years of effort in this project.
12.4.1 is the first release on PyPI since the migration to the Jazzband
project, and includes two years' worth of changes. Thank you to all
contributors. These are some of the highlights:
* Target Django versions are now 1.8, 1.10, 1.11 and 2.0
* Target Python versions are now 2.7, 3.3, 3.4, 3.5 and 3.6
* Enable GIF support (#263)
* Enable WebP support (#460)
* New ``sorl_thumbnail`` templatetag library that mirrors traditional ``thumbnail``
* Fix bug RGBA mode not compatible with JPEG on PILLOW >=3.7 (#503)
* Don't check EXIF orientation with GraphicsMagick
* Bug fix for handling non-ASCII characters in filenames (#434)
* Better error detection and handling in some cases (#492)
* Improve automated testing
* Improve documentation
sorl-thumbnail-12.10.0/CODE_OF_CONDUCT.md 0000664 0000000 0000000 00000004507 14507342020 0017415 0 ustar 00root root 0000000 0000000 # Code of Conduct
As contributors and maintainers of the Jazzband projects, and in the interest of
fostering an open and welcoming community, we pledge to respect all people who
contribute through reporting issues, posting feature requests, updating documentation,
submitting pull requests or patches, and other activities.
We are committed to making participation in the Jazzband a harassment-free experience
for everyone, regardless of the level of experience, gender, gender identity and
expression, sexual orientation, disability, personal appearance, body size, race,
ethnicity, age, religion, or nationality.
Examples of unacceptable behavior by participants include:
- The use of sexualized language or imagery
- Personal attacks
- Trolling or insulting/derogatory comments
- Public or private harassment
- Publishing other's private information, such as physical or electronic addresses,
without explicit permission
- Other unethical or unprofessional conduct
The Jazzband roadies have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are not
aligned to this Code of Conduct, or to ban temporarily or permanently any contributor
for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
By adopting this Code of Conduct, the roadies commit themselves to fairly and
consistently applying these principles to every aspect of managing the jazzband
projects. Roadies who do not follow or enforce the Code of Conduct may be permanently
removed from the Jazzband roadies.
This code of conduct applies both within project spaces and in public spaces when an
individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by
contacting the roadies at `roadies@jazzband.co`. All complaints will be reviewed and
investigated and will result in a response that is deemed necessary and appropriate to
the circumstances. Roadies are obligated to maintain confidentiality with regard to the
reporter of an incident.
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version
1.3.0, available at [https://contributor-covenant.org/version/1/3/0/][version]
[homepage]: https://contributor-covenant.org
[version]: https://contributor-covenant.org/version/1/3/0/
sorl-thumbnail-12.10.0/CONTRIBUTING.rst 0000664 0000000 0000000 00000000533 14507342020 0017252 0 ustar 00root root 0000000 0000000 |Jazzband|
This is a `Jazzband `__ project. By contributing
you agree to abide by the `Contributor Code of
Conduct `__ and follow the
`guidelines `__.
.. |Jazzband| image:: https://jazzband.co/static/img/jazzband.svg
:target: https://jazzband.co/
sorl-thumbnail-12.10.0/LICENSE 0000664 0000000 0000000 00000002756 14507342020 0015627 0 ustar 00root root 0000000 0000000 Copyright (c) 2010, Mikko Hellsing
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the sorl-thumbnail the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
sorl-thumbnail-12.10.0/MANIFEST.in 0000664 0000000 0000000 00000000222 14507342020 0016342 0 ustar 00root root 0000000 0000000 include LICENSE README.rst CHANGES.rst AUTHORS.rst
recursive-include docs *
recursive-include tests *
recursive-exclude * *.pyc
prune docs/_build
sorl-thumbnail-12.10.0/README.rst 0000664 0000000 0000000 00000016153 14507342020 0016305 0 ustar 00root root 0000000 0000000 |jazzband-badge| |pypi| |python-badge| |django-badge| |docs| |gh-actions| |codecov|
Thumbnails for Django.
Features at a glance
====================
- Support for Django 3.2, 4.0 and 4.1 following the `Django supported versions policy`_
- Python 3 support
- Storage support
- Pluggable Engine support for `Pillow`_, `ImageMagick`_, `PIL`_, `Wand`_, `pgmagick`_, and `vipsthumbnail`_
- Pluggable Key Value Store support (cached db, redis, and dynamodb by AWS)
- Pluggable Backend support
- Admin integration with possibility to delete
- Dummy generation (placeholders)
- Flexible, simple syntax, generates no html
- ImageField for model that deletes thumbnails (only compatible with django 1.2.5 or less)
- CSS style cropping options
- Back smart cropping, and remove borders from the images when cropping
- Margin calculation for vertical positioning
- Alternative resolutions versions of a thumbnail
Read more in `the documentation (latest version) `_
Developers
==========
|jazzband|
This is a `Jazzband `_ project. By contributing you agree to
abide by the `Contributor Code of Conduct `_
and follow the `guidelines `_.
Feel free to create a new Pull request if you want to propose a new feature.
If you need development support or want to discuss with other developers
join us in the channel #sorl-thumbnail at freenode.net or Gitter.
For releases updates and more in deep development discussion use our mailing list
in Google Groups.
- IRC Channel: irc://irc.freenode.net/#sorl-thumbnail
- Mailing List: sorl-thumbnail@googlegroups.com https://groups.google.com/d/forum/sorl-thumbnail
Tests
-----
The tests should run with tox and pytest. Running `tox` will run all tests for all environments.
However, it is possible to run a certain environment with `tox -e `, a list of all environments
can be found with `tox -l`. These tests require the dependencies of the different engines defined in
the documentation. It is possible to install these dependencies into a vagrant image with the
Vagrantfile in the repo.
User Support
============
If you need help using sorl-thumbnail browse https://stackoverflow.com/questions/tagged/sorl-thumbnail
and posts your questions with the `sorl-thumbnail` tag.
How to Use
==========
Get the code
------------
Getting the code for the latest stable release use 'pip'. ::
$ pip install sorl-thumbnail
Install in your project
-----------------------
Then register 'sorl.thumbnail', in the 'INSTALLED_APPS' section of
your project's settings. ::
INSTALLED_APPS = [
'django.contrib.auth',
'django.contrib.admin',
'django.contrib.sites',
'django.contrib.comments',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.contenttypes',
'sorl.thumbnail',
]
Templates Usage
---------------
All of the examples assume that you first load the thumbnail template tag in
your template.::
{% load thumbnail %}
A simple usage. ::
{% thumbnail item.image "100x100" crop="center" as im %}
{% endthumbnail %}
See more examples in the section `Template examples`_ in the Documentation
Model Usage
-----------
Using the ImageField that automatically deletes references to itself in the key
value store and its thumbnail references and the thumbnail files when deleted.
Please note that this is only compatible with django 1.2.5 or less.::
from django.db import models
from sorl.thumbnail import ImageField
class Item(models.Model):
image = ImageField(upload_to='whatever')
See more examples in the section `Model examples`_ in the Documentation
Low level API
-------------
You can use the 'get_thumbnail'::
from sorl.thumbnail import get_thumbnail
from sorl.thumbnail import delete
im = get_thumbnail(my_file, '100x100', crop='center', quality=99)
delete(my_file)
See more examples in the section `Low level API examples`_ in the Documentation
Using in combination with other thumbnailers
--------------------------------------------
Alternatively, you load the templatetags by {% load sorl_thumbnail %}
instead of traditional {% load thumbnail %}. It's especially useful in
projects that do make use of multiple thumbnailer libraries that use the
same name (``thumbnail``) for the templatetag module::
{% load sorl_thumbnail %}
{% thumbnail item.image "100x100" crop="center" as im %}
{% endthumbnail %}
Frequently asked questions
==========================
Is so slow in Amazon S3!
------------------------
Possible related to the implementation of your Amazon S3 Backend, see the `issue #351`_
due the storage backend reviews if there is an existing thumbnail when tries to
generate the thumbnail that makes an extensive use of the S3 API
A fast workaround if you are not willing to tweak your storage backend is to set::
THUMBNAIL_FORCE_OVERWRITE = True
So it will avoid to overly query the S3 API.
.. |gh-actions| image:: https://github.com/jazzband/sorl-thumbnail/workflows/Test/badge.svg
:target: https://github.com/jazzband/sorl-thumbnail/actions
.. |docs| image:: https://readthedocs.org/projects/pip/badge/?version=latest
:alt: Documentation for latest version
:target: https://sorl-thumbnail.readthedocs.io/en/latest/
.. |pypi| image:: https://img.shields.io/pypi/v/sorl-thumbnail.svg
:target: https://pypi.python.org/pypi/sorl-thumbnail
:alt: sorl-thumbnail on PyPI
.. |python-badge| image:: https://img.shields.io/pypi/pyversions/sorl-thumbnail.svg
:target: https://pypi.python.org/pypi/sorl-thumbnail
:alt: Supported Python versions
.. |django-badge| image:: https://img.shields.io/pypi/djversions/sorl-thumbnail.svg
:target: https://pypi.python.org/pypi/sorl-thumbnail
:alt: Supported Python versions
.. |codecov| image:: https://codecov.io/gh/jazzband/sorl-thumbnail/branch/master/graph/badge.svg
:target: https://codecov.io/gh/jazzband/sorl-thumbnail
:alt: Coverage
.. |jazzband-badge| image:: https://jazzband.co/static/img/badge.svg
:target: https://jazzband.co/
:alt: Jazzband
.. |jazzband| image:: https://jazzband.co/static/img/jazzband.svg
:target: https://jazzband.co/
:alt: Jazzband
.. _`Pillow`: https://pillow.readthedocs.io/
.. _`ImageMagick`: https://imagemagick.org/
.. _`PIL`: https://python-pillow.org/
.. _`Wand`: https://docs.wand-py.org/
.. _`pgmagick`: https://pgmagick.readthedocs.io/
.. _`vipsthumbnail`: https://www.libvips.org/API/current/Using-vipsthumbnail.html
.. _`Template examples`: https://sorl-thumbnail.readthedocs.io/en/latest/examples.html#template-examples
.. _`Model examples`: https://sorl-thumbnail.readthedocs.io/en/latest/examples.html#model-examples
.. _`Low level API examples`: https://sorl-thumbnail.readthedocs.io/en/latest/examples.html#low-level-api-examples
.. _`issue #351`: https://github.com/jazzband/sorl-thumbnail/issues/351
.. _`Django supported versions policy`: https://www.djangoproject.com/download/#supported-versions
sorl-thumbnail-12.10.0/Vagrantfile 0000664 0000000 0000000 00000000427 14507342020 0017000 0 ustar 00root root 0000000 0000000 # -*- mode: ruby -*-
# vi: set ft=ruby :
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "precise64"
config.vm.box_url = "http://files.vagrantup.com/precise64.box"
config.vm.provision :shell, :path => "vagrant.sh"
end
sorl-thumbnail-12.10.0/codecov.yml 0000664 0000000 0000000 00000000073 14507342020 0016755 0 ustar 00root root 0000000 0000000 coverage:
precision: 2
round: down
range: "60...100"
sorl-thumbnail-12.10.0/docs/ 0000775 0000000 0000000 00000000000 14507342020 0015540 5 ustar 00root root 0000000 0000000 sorl-thumbnail-12.10.0/docs/Makefile 0000664 0000000 0000000 00000011012 14507342020 0017173 0 ustar 00root root 0000000 0000000 # Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
help:
@echo "Please use \`make ' where is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
-rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/sorlthumbnail.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/sorlthumbnail.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/sorlthumbnail"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/sorlthumbnail"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
make -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
sorl-thumbnail-12.10.0/docs/_theme/ 0000775 0000000 0000000 00000000000 14507342020 0017001 5 ustar 00root root 0000000 0000000 sorl-thumbnail-12.10.0/docs/_theme/nature/ 0000775 0000000 0000000 00000000000 14507342020 0020277 5 ustar 00root root 0000000 0000000 sorl-thumbnail-12.10.0/docs/_theme/nature/static/ 0000775 0000000 0000000 00000000000 14507342020 0021566 5 ustar 00root root 0000000 0000000 sorl-thumbnail-12.10.0/docs/_theme/nature/static/nature.css_t 0000664 0000000 0000000 00000007440 14507342020 0024126 0 ustar 00root root 0000000 0000000 /**
* Sphinx stylesheet -- default theme
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
@import url("basic.css");
/* -- page layout ----------------------------------------------------------- */
body {
font-family: Arial, sans-serif;
font-size: 100%;
background-color: #111;
color: #555;
margin: 0;
padding: 0;
}
div.documentwrapper {
float: left;
width: 100%;
}
div.bodywrapper {
margin: 0 0 0 230px;
}
hr{
border: 1px solid #B1B4B6;
}
div.document {
background-color: #eee;
}
div.body {
background-color: #ffffff;
color: #3E4349;
padding: 0 30px 30px 30px;
font-size: 0.8em;
}
div.footer {
color: #555;
width: 100%;
padding: 13px 0;
text-align: center;
font-size: 75%;
}
div.footer a {
color: #444;
text-decoration: underline;
}
div.related {
background-color: #6BA81E;
line-height: 32px;
color: #fff;
text-shadow: 0px 1px 0 #444;
font-size: 0.80em;
}
div.related a {
color: #E2F3CC;
}
div.sphinxsidebar {
font-size: 0.75em;
line-height: 1.5em;
}
div.sphinxsidebarwrapper{
padding: 20px 0;
}
div.sphinxsidebar h3,
div.sphinxsidebar h4 {
font-family: Arial, sans-serif;
color: #222;
font-size: 1.2em;
font-weight: normal;
margin: 0;
padding: 5px 10px;
background-color: #ddd;
text-shadow: 1px 1px 0 white
}
div.sphinxsidebar h4{
font-size: 1.1em;
}
div.sphinxsidebar h3 a {
color: #444;
}
div.sphinxsidebar p {
color: #888;
padding: 5px 20px;
}
div.sphinxsidebar p.topless {
}
div.sphinxsidebar ul {
margin: 10px 20px;
padding: 0;
color: #000;
}
div.sphinxsidebar a {
color: #444;
}
div.sphinxsidebar input {
border: 1px solid #ccc;
font-family: sans-serif;
font-size: 1em;
}
div.sphinxsidebar input[type=text]{
margin-left: 20px;
}
/* -- body styles ----------------------------------------------------------- */
a {
color: #005B81;
text-decoration: none;
}
a:hover {
color: #E32E00;
text-decoration: underline;
}
div.body h1,
div.body h2,
div.body h3,
div.body h4,
div.body h5,
div.body h6 {
font-family: Arial, sans-serif;
background-color: #BED4EB;
font-weight: normal;
color: #212224;
margin: 30px 0px 10px 0px;
padding: 5px 0 5px 10px;
text-shadow: 0px 1px 0 white
}
div.body h1 { border-top: 20px solid white; margin-top: 0; font-size: 200%; }
div.body h2 { font-size: 150%; background-color: #C8D5E3; }
div.body h3 { font-size: 120%; background-color: #D8DEE3; }
div.body h4 { font-size: 110%; background-color: #D8DEE3; }
div.body h5 { font-size: 100%; background-color: #D8DEE3; }
div.body h6 { font-size: 100%; background-color: #D8DEE3; }
a.headerlink {
color: #c60f0f;
font-size: 0.8em;
padding: 0 4px 0 4px;
text-decoration: none;
}
a.headerlink:hover {
background-color: #c60f0f;
color: white;
}
div.body p, div.body dd, div.body li {
line-height: 1.5em;
}
div.admonition p.admonition-title + p {
display: inline;
}
div.highlight{
background-color: white;
}
div.note {
background-color: #eee;
border: 1px solid #ccc;
}
div.seealso {
background-color: #ffc;
border: 1px solid #ff6;
}
div.topic {
background-color: #eee;
}
div.warning {
background-color: #ffe4e4;
border: 1px solid #f66;
}
p.admonition-title {
display: inline;
}
p.admonition-title:after {
content: ":";
}
pre {
padding: 10px;
background-color: White;
color: #222;
line-height: 1.2em;
border: 1px solid #C6C9CB;
font-size: 1.2em;
margin: 1.5em 0 1.5em 0;
-webkit-box-shadow: 1px 1px 1px #d8d8d8;
-moz-box-shadow: 1px 1px 1px #d8d8d8;
}
tt {
background-color: #ecf0f3;
color: #222;
padding: 1px 2px;
font-size: 1.2em;
font-family: monospace;
}
sorl-thumbnail-12.10.0/docs/_theme/nature/static/pygments.css 0000664 0000000 0000000 00000005235 14507342020 0024153 0 ustar 00root root 0000000 0000000 .c { color: #999988; font-style: italic } /* Comment */
.k { font-weight: bold } /* Keyword */
.o { font-weight: bold } /* Operator */
.cm { color: #999988; font-style: italic } /* Comment.Multiline */
.cp { color: #999999; font-weight: bold } /* Comment.preproc */
.c1 { color: #999988; font-style: italic } /* Comment.Single */
.gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.ge { font-style: italic } /* Generic.Emph */
.gr { color: #aa0000 } /* Generic.Error */
.gh { color: #999999 } /* Generic.Heading */
.gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.go { color: #111 } /* Generic.Output */
.gp { color: #555555 } /* Generic.Prompt */
.gs { font-weight: bold } /* Generic.Strong */
.gu { color: #aaaaaa } /* Generic.Subheading */
.gt { color: #aa0000 } /* Generic.Traceback */
.kc { font-weight: bold } /* Keyword.Constant */
.kd { font-weight: bold } /* Keyword.Declaration */
.kp { font-weight: bold } /* Keyword.Pseudo */
.kr { font-weight: bold } /* Keyword.Reserved */
.kt { color: #445588; font-weight: bold } /* Keyword.Type */
.m { color: #009999 } /* Literal.Number */
.s { color: #bb8844 } /* Literal.String */
.na { color: #008080 } /* Name.Attribute */
.nb { color: #999999 } /* Name.Builtin */
.nc { color: #445588; font-weight: bold } /* Name.Class */
.no { color: #ff99ff } /* Name.Constant */
.ni { color: #800080 } /* Name.Entity */
.ne { color: #990000; font-weight: bold } /* Name.Exception */
.nf { color: #990000; font-weight: bold } /* Name.Function */
.nn { color: #555555 } /* Name.Namespace */
.nt { color: #000080 } /* Name.Tag */
.nv { color: purple } /* Name.Variable */
.ow { font-weight: bold } /* Operator.Word */
.mf { color: #009999 } /* Literal.Number.Float */
.mh { color: #009999 } /* Literal.Number.Hex */
.mi { color: #009999 } /* Literal.Number.Integer */
.mo { color: #009999 } /* Literal.Number.Oct */
.sb { color: #bb8844 } /* Literal.String.Backtick */
.sc { color: #bb8844 } /* Literal.String.Char */
.sd { color: #bb8844 } /* Literal.String.Doc */
.s2 { color: #bb8844 } /* Literal.String.Double */
.se { color: #bb8844 } /* Literal.String.Escape */
.sh { color: #bb8844 } /* Literal.String.Heredoc */
.si { color: #bb8844 } /* Literal.String.Interpol */
.sx { color: #bb8844 } /* Literal.String.Other */
.sr { color: #808000 } /* Literal.String.Regex */
.s1 { color: #bb8844 } /* Literal.String.Single */
.ss { color: #bb8844 } /* Literal.String.Symbol */
.bp { color: #999999 } /* Name.Builtin.Pseudo */
.vc { color: #ff99ff } /* Name.Variable.Class */
.vg { color: #ff99ff } /* Name.Variable.Global */
.vi { color: #ff99ff } /* Name.Variable.Instance */
.il { color: #009999 } /* Literal.Number.Integer.Long */ sorl-thumbnail-12.10.0/docs/_theme/nature/theme.conf 0000664 0000000 0000000 00000000107 14507342020 0022246 0 ustar 00root root 0000000 0000000 [theme]
inherit = basic
stylesheet = nature.css
pygments_style = tango
sorl-thumbnail-12.10.0/docs/conf.py 0000664 0000000 0000000 00000015323 14507342020 0017043 0 ustar 00root root 0000000 0000000 # sorl-thumbnail documentation build configuration file, created by
# sphinx-quickstart on Fri Nov 12 00:51:21 2010.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import pkg_resources
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.viewcode']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = 'sorl-thumbnail'
copyright = '2010, Mikko Hellsing'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = pkg_resources.get_distribution("sorl-thumbnail").version
# The full version, including alpha/beta/rc tags.
release = version
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#html_theme = 'default'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = ['_theme']
# The name for this set of Sphinx documents. If None, it defaults to
# " v documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
# html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'sorlthumbnaildoc'
# -- Options for LaTeX output --------------------------------------------------
# The paper size ('letter' or 'a4').
#latex_paper_size = 'letter'
# The font size ('10pt', '11pt' or '12pt').
#latex_font_size = '10pt'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'sorlthumbnail.tex', 'sorl-thumbnail Documentation',
'Mikko Hellsing', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Additional stuff for the LaTeX preamble.
#latex_preamble = ''
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'sorlthumbnail', 'sorl-thumbnail Documentation',
['Mikko Hellsing'], 1)
]
sorl-thumbnail-12.10.0/docs/contributing.rst 0000664 0000000 0000000 00000005176 14507342020 0021012 0 ustar 00root root 0000000 0000000 ************
Contributing
************
Feel free to create a new Pull request if you want to propose a new feature
or fix a bug. If you need development support or want to discuss
with other developers, join us in the channel #sorl-thumbnail at freenode.net
irc://irc.freenode.net/#sorl-thumbnail
Running testsuit
================
For occasional developers we recommend using `GitHub Actions`_ to run testsuite,
for those who want to run tests locally, read on.
Since sorl-thumbnail supports a variety of image backends, python and
Django versions, we provide an easy way to test locally across all of them.
We use `Vagrant`_ for simple interaction with virtual machines and
`tox`_ for managing python virtual environments.
Some dependencies like pgmagick takes a lot of time to compiling. To speed up your
vagrant box you can edit `Vagrant file`_ with mem and cpu or simply install `vagrant-faster`_.
The resulting .tox folder containing all virtualenvs requires ~
* `Install Vagrant`_
* ``cd`` in your source directory
* Run ``vagrant up`` to prepare VM. It will download Ubuntu image and install all necessary dependencies.
* Run ``vagrant ssh`` to log in the VM
* Launch all tests via ``tox`` (will take some time to build envs first time)
To run only tests against only one configuration use ``-e`` option::
tox -e py34-django16-pil
Py34 stands for python version, 1.6 is Django version and the latter is image library.
For full list of tox environments, see ``tox.ini``
You can get away without using Vagrant if you install all packages locally yourself,
however, this is not recommended.
.. _GitHub Actions: https://github.com/jazzband/sorl-thumbnail/actions
.. _Vagrant: https://www.vagrantup.com/
.. _tox: https://tox.wiki/
.. _Install Vagrant: https://www.vagrantup.com/docs/installation
.. _Vagrant file: https://www.vagrantup.com/docs/providers/virtualbox/configuration
.. _vagrant-faster: https://github.com/rdsubhas/vagrant-faster
Sending pull requests
=====================
1. Fork the repo::
git@github.com:jazzband/sorl-thumbnail.git
2. Create a branch for your specific changes::
$ git checkout master
$ git pull
$ git checkout -b feature/foobar
To simplify things, please, make one branch per issue (pull request).
It's also important to make sure your branch is up-to-date with upstream master,
so that maintainers can merge changes easily.
3. Commit changes. Please update docs, if relevant.
4. Don't forget to run tests to check than nothing breaks.
5. Ideally, write your own tests for new feature/bug fix.
6. Submit a `pull request`_.
.. _pull request: https://help.github.com/articles/using-pull-requests
sorl-thumbnail-12.10.0/docs/examples.rst 0000664 0000000 0000000 00000011533 14507342020 0020113 0 ustar 00root root 0000000 0000000 ********
Examples
********
Template examples
=================
.. highlight:: html+django
All of the examples assume that you first load the ``thumbnail`` template tag in
your template::
{% load thumbnail %}
Simple::
{% thumbnail item.image "100x100" crop="center" as im %}
{% endthumbnail %}
Crop using margin filter, x, y aliases::
{% thumbnail item.image "100x700" as im %}
{% endthumbnail %}
Using external images and advanced cropping::
{% thumbnail "http://www.aino.se/media/i/logo.png" "40x40" crop="80% top" as im %}
{% endthumbnail %}
Using the empty feature, the empty section is rendered when the source is
resolved to an empty value or an invalid image source, you can think of it as
rendering when the thumbnail becomes undefined::
{% thumbnail item.image my_size_string crop="left" as im %}
{% empty %}
No image
{% endthumbnail %}
Nesting tags and setting size (geometry) for width only::
{% thumbnail item.image "1000" as big %}
{% thumbnail item.image "50x50" crop="center" as small %}
{% endthumbnail %}
{% endthumbnail %}
Setting geometry for height only::
{% thumbnail item.image "x300" as im %}
{% endthumbnail %}
Setting format and using the is_portrait filter::
{% if item.image|is_portrait %}
{% thumbnail item.image "100" crop="10px 10px" format="PNG" as im %}
{% endthumbnail %}
{% else %}
{% thumbnail item.image "50" crop="bottom" format="PNG" as im %}
{% endthumbnail %}
Undefined behaviour
{% endif %}
Using HTML filter::
{{ text|html_thumbnails }}
Using markdown filter::
{{ text|markdown_thumbnails }}
.. highlight:: python
Model examples
==============
Using the ImageField that automatically deletes references to itself in the key
value store and its thumbnail references when deleted::
from django.db import models
from sorl.thumbnail import ImageField
class Item(models.Model):
image = ImageField(upload_to='whatever')
.. note:: You do not need to use the ``sorl.thumbnail.ImageField`` to use
``sorl.thumbnail``. The standard ``django.db.models.ImageField`` is fine
except that using the ``sorl.thumbnail.ImageField`` lets you plugin the
nice admin addition explained in the next section.
Another example on how to use ``sorl.thumbnail.ImageField`` in your existing
project with only small code changes::
# util/models.py
from django.db.models import *
from sorl.thumbnail import ImageField
# myapp/models.py
from util import models
class MyModel(models.Model):
logo = ImageField(upload_to='/dev/null')
Admin examples
==============
Recommended usage using ``sorl.thumbnail.admin.AdminImageMixin`` (note that this requires use of ``sorl.thumbnail.ImageField`` in your models as explained above)::
# myapp/admin.py
from django.contrib import admin
from myapp.models import MyModel
from sorl.thumbnail.admin import AdminImageMixin
class MyModelAdmin(AdminImageMixin, admin.ModelAdmin):
pass
And the same thing For inlines::
# myapp/admin.py
from django.contrib import admin
from myapp.models import MyModel, MyInlineModel
from sorl.thumbnail.admin import AdminImageMixin
class MyInlineModelAdmin(AdminImageMixin, admin.TabularInline):
model = MyInlineModel
class MyModelAdmin(admin.ModelAdmin):
inlines = [MyInlineModelAdmin]
Easy to plugin solution example with little code to change::
# util/admin.py
from django.contrib.admin import *
from sorl.thumbnail.admin import AdminImageMixin
class ModelAdmin(AdminImageMixin, ModelAdmin):
pass
class TabularInline(AdminImageMixin, TabularInline):
pass
class StackedInline(AdminImageMixin, StackedInline):
pass
# myapp/admin.py
from util import admin
from myapp.models import MyModel
class MyModelAdmin(admin.ModelAdmin):
pass
Low level API examples
======================
How to get make a thumbnail in your python code::
from sorl.thumbnail import get_thumbnail
im = get_thumbnail(my_file, '100x100', crop='center', quality=99)
How to delete a file, its thumbnails as well as references in the Key Value
Store::
from sorl.thumbnail import delete
delete(my_file)
sorl-thumbnail-12.10.0/docs/index.rst 0000664 0000000 0000000 00000000546 14507342020 0017406 0 ustar 00root root 0000000 0000000 ******************************
sorl-thumbnail's documentation
******************************
Contents:
.. toctree::
:maxdepth: 2
examples
installation
requirements
template
management
logging
operation
reference/index
contributing
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
sorl-thumbnail-12.10.0/docs/installation.rst 0000664 0000000 0000000 00000001046 14507342020 0020774 0 ustar 00root root 0000000 0000000 ********************
Installation & Setup
********************
Installation
============
First you need to make sure to read the :doc:`requirements`. To install
sorl-thumbnail is easy::
pip install sorl-thumbnail
Or you can go to `the github page `_
Setup
=====
.. highlight:: python
1. Add ``sorl.thumbnail`` to your ``settings.INSTALLED_APPS``.
2. Configure your ``settings``
3. If you are using the cached database key value store you need to sync the
database::
python manage.py migrate
sorl-thumbnail-12.10.0/docs/logging.rst 0000664 0000000 0000000 00000002164 14507342020 0017723 0 ustar 00root root 0000000 0000000 ****************
Errors & Logging
****************
.. highlight:: python
Background
==========
When ``THUMBNAIL_DEBUG = False`` errors will be suppressed if they are raised
during rendering the ``thumbnail`` tag or raised within the included filters.
This is the recommended production setting. However it can still be useful to be
notified of those errors. Thus sorl-thumbnail logs errors to a logger and
provides a log handler that sends emails to ``settings.ADMINS``.
How to setup logging
====================
To enable logging you need to add a handler to the 'sorl.thumbnail' logger.
The following example adds the provided handler that sends emails to site admins
in case an error is raised with debugging off::
import logging
from sorl.thumbnail.log import ThumbnailLogHandler
handler = ThumbnailLogHandler()
handler.setLevel(logging.ERROR)
logging.getLogger('sorl.thumbnail').addHandler(handler)
You will need to load this code somewhere in your django project, it could be
in urls.py, settings.py or project/app __init__.py file for example. You could
of course also provide your own logging handler.
sorl-thumbnail-12.10.0/docs/make.bat 0000664 0000000 0000000 00000010030 14507342020 0017137 0 ustar 00root root 0000000 0000000 @ECHO OFF
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=_build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^` where ^ is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. devhelp to make HTML files and a Devhelp project
echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. text to make text files
echo. man to make manual pages
echo. changes to make an overview over all changed/added/deprecated items
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\sorlthumbnail.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\sorlthumbnail.ghc
goto end
)
if "%1" == "devhelp" (
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
echo.
echo.Build finished.
goto end
)
if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)
if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
:end
sorl-thumbnail-12.10.0/docs/management.rst 0000664 0000000 0000000 00000004173 14507342020 0020413 0 ustar 00root root 0000000 0000000 *******************
Management commands
*******************
.. highlight:: python
.. _thumbnail-cleanup:
thumbnail cleanup
=================
``python manage.py thumbnail cleanup``
This cleans up the Key Value Store from stale cache. It removes references to
images that do not exist and thumbnail references and their actual files for
images that do not exist. It removes thumbnails for unknown images.
.. _thumbnail-clear:
thumbnail clear
===============
``python manage.py thumbnail clear``
This totally empties the Key Value Store of all keys that start with the
``settings.THUMBNAIL_KEY_PREFIX``. It does not delete any files. The Key Value
store will update when you hit the template tags, and if the thumbnails files
still exist they will be used and not overwritten/regenerated. This can be
useful if your Key Value Store has garbage data not dealt with by cleanup or
you're switching Key Value Store backend.
.. _thumbnail-clear-delete-referenced:
thumbnail clear_delete_referenced
=================================
``python manage.py thumbnail clear_delete_referenced``
Equivalent to ``clear`` but first it will delete all thumbnail files
referenced by the Key Value Store. It is generally safe to run this if you do
not reference the generated thumbnails by name somewhere else in your code. As
long as all the original images still exist this will trigger a regeneration of
all the thumbnails the Key Value Store knows about.
.. _thumbnail-clear-delete-all:
thumbnail clear_delete_all
==========================
``python manage.py thumbnail clear_delete_all``
Equivalent to to ``clear`` but afterwards it will delete all thumbnail files
including any orphans not in the Key Value Store. This can be thought of as a
more aggressive version of ``clear_delete_referenced``. Caution should be
exercised with this command if multiple Django sites (as in ``SITE_ID``) or
projects are using the same ``MEDIA_ROOT`` since this will clear out absolutely
everything in the thumbnail cache directory causing thumbnail regeneration for
all sites and projects. When file system storage is used, it is equivalent to
``rm -rf MEDIA_ROOT + THUMBNAIL_PREFIX``
sorl-thumbnail-12.10.0/docs/operation.rst 0000664 0000000 0000000 00000006173 14507342020 0020301 0 ustar 00root root 0000000 0000000 ***************************
How sorl-thumbnail operates
***************************
.. highlight:: python
When you use the ``thumbnail`` template tag sorl-thumbnail looks up the
thumbnail in a :ref:`kvstore-requirements`. The key for a thumbnail is
generated from its filename and storage. The thumbnail filename in turn is
generated from the source and requested thumbnail size and options. If the key
for the thumbnail is found in the |kvstore|, the serialized thumbnail
information is fetched from it and returned. If the thumbnail key is not found
there sorl-thumbnail continues to generate the thumbnail and stores necessary
information in the |kvstore|. It is worth noting that sorl-thumbnail does not
check if source or thumbnail exists if the thumbnail key is found in the
|kvstore|.
.. note:: This means that if you change or delete a source file or delete the
thumbnail, sorl-thumbnail will still fetch from the |kvstore|.
Therefore it is important that if you delete or change a source or
thumbnail file notify the |kvstore|.
If you change or delete a source or a thumbnail for some reason, you can use
the ``delete`` method of the ``ThumbnailBackend`` class or subclass::
from sorl.thumbnail import delete
# Delete the Key Value Store reference but **not** the file.
# Use this if you have changed the source
delete(my_file, delete_file=False)
# Delete the Key Value Store reference and the file
# Use this if you want to delete the source file
delete(my_file) # delete_file=True is default
The ``sorl.thumbnail.delete`` method always deletes the input files thumbnail
Key Value Store references as well as thumbnail files. You can use this method
on thumbnails as well as source files. Alternatively if you have **deleted** a
file you can use the management command :ref:`thumbnail-cleanup`. Deleting an
image using the ``sorl.thumbnail.ImageField`` will notify the |kvstore| to
delete references to it and delete all of its thumbnail references and files,
exactly like the above code example.
**Why you ask?** Why go through all the trouble with a |kvstore| and risk
stale cache? Why not use a database to cache if you are going to do that?
The reason is speed and especially with storages other than local file storage.
Checking if a file exists before serving it will cost too much. Speed is also
the reason for not choosing to use a standard database for this kind of
persistent caching. However sorl-thumbnail does ship with a *cached* database
|kvstore|.
.. note:: We have to assume the thumbnail exists if the thumbnail key exists in
the |kvstore|
**There are bonuses**. We can store meta data in the |kvstore| that would be
too costly to retrieve even for local file storage. Today this meta data
consists only of the image size but this could be expanded to for example EXIF
data. The other bonus is that we can keep track of what thumbnails has been
generated from a particular source and deleting them too when the source is
deleted.
`Schematic view of how things are done
`_
.. |kvstore| replace:: Key Value Store
sorl-thumbnail-12.10.0/docs/reference/ 0000775 0000000 0000000 00000000000 14507342020 0017476 5 ustar 00root root 0000000 0000000 sorl-thumbnail-12.10.0/docs/reference/image.rst 0000664 0000000 0000000 00000003613 14507342020 0021315 0 ustar 00root root 0000000 0000000 *********
ImageFile
*********
.. highlight:: html+django
``ImageFile`` is an image abstraction that contains useful attributes when
working with images. The ``thumbnail`` template tag puts the generated thumbnail
in context as an ``ImageFile`` instance. In the following example::
{% thumbnail item.image "100x100" as im %}
{% endthumbnail %}
``im`` will be an ``ImageFile`` instance.
.. highlight:: python
ImageFile attributes
====================
``name``
--------
Name of the image as returned from the underlying storage.
``storage``
-----------
Returns the storage instance.
``width``
---------
Returns the width of the image in pixels.
``x``
-----
Alias of ``width``
``height``
----------
Returns the height of the image in pixels.
``y``
-----
Alias of ``height``
``ratio``
---------
Returns the image ratio (y/x) as a float
``url``
-------
URL of the image url as returned by the underlying storage.
``src``
-------
Alias of ``url``
``size``
--------
Returns the image size in pixels as a (x, y) tuple
``key``
-------
Returns a unique key based on ``name`` and ``storage``.
ImageFile methods
=================
``exists``
----------
Returns whether the file exists as returned by the underlying storage.
``is_portrait``
---------------
Returns ``True`` if ``y > x``, else ``False``
``set_size``
------------
Sets the size of the image, takes an optional size tuple (x, y) as argument.
``read``
--------
Reads the file as done from the underlying storage.
``write``
---------
Writes content to the file. Takes content as argument. Content is either raw
data or an instance of ``django.core.files.base.ContentFile``.
``delete``
----------
Deletes the file from underlying storage.
``serialize``
-------------
Returns a serialized version of self.
``serialize_storage``
---------------------
Returns the ``self.storage`` as a serialized dot name path string.
sorl-thumbnail-12.10.0/docs/reference/index.rst 0000664 0000000 0000000 00000000123 14507342020 0021333 0 ustar 00root root 0000000 0000000 *********
Reference
*********
.. toctree::
:maxdepth: 2
image
settings
sorl-thumbnail-12.10.0/docs/reference/settings.rst 0000664 0000000 0000000 00000023712 14507342020 0022075 0 ustar 00root root 0000000 0000000 ********
Settings
********
.. highlight:: python
``THUMBNAIL_DEBUG``
===================
- Default: ``False``
When set to ``True`` the ``ThumbnailNode.render`` method can raise errors.
Django recommends that tags never raise errors in the ``Node.render`` method
but since sorl-thumbnail is such a complex tag we will need to have more
debugging available.
``THUMBNAIL_BACKEND``
=====================
- Default: ``'sorl.thumbnail.base.ThumbnailBackend'``
This is the entry point for generating thumbnails, you probably want to keep the
default one but just in case you would like to generate thumbnails filenames
differently or need some special functionality you can override this and use
your own implementation.
``THUMBNAIL_KVSTORE``
=====================
- Default: ``'sorl.thumbnail.kvstores.cached_db_kvstore.KVStore'``
sorl-thumbnail needs a Key Value Store to :doc:`/operation`.
sorl-thumbnail ships with support for three Key Value Stores:
Cached DB
---------
``sorl.thumbnail.kvstores.cached_db_kvstore.KVStore``. This is the default and
preferred Key Value Store.
Features
^^^^^^^^
* Fast persistent storage
* First query uses database which is slow. Successive queries are cached and if
you use memcached this is very fast.
* Easy to transfer data between environments since the data is in the default
database.
* If you get the database and fast cache out of sync there could be problems.
Redis
-----
``sorl.thumbnail.kvstores.redis_kvstore.KVStore``. It requires you to install a
Redis server as well as a `redis python client
`_.
Features
^^^^^^^^
* Fast persistent storage
* More dependencies
* Requires a little extra work to transfer data between environments
Dbm
---
``sorl.thumbnail.kvstores.dbm_kvstore.KVStore``. A simple Key Value Store has no
dependencies outside the standard Python library and uses the DBM modules to
store the data.
Features
^^^^^^^^
* No external dependencies, besides the standard library
* No extra components required, e.g., database or cache
* Specially indicated for local development environments
``THUMBNAIL_KEY_DBCOLUMN``
==========================
- Default ``'key'``
Since MSSQL reserved the ``key`` name for db columns you can change this to
something else using this setting.
``THUMBNAIL_ENGINE``
====================
- Default: ``'sorl.thumbnail.engines.pil_engine.Engine'``
This is the processing class for sorl-thumbnail. It does all the resizing,
cropping or whatever processing you want to perform. sorl-thumbnail ships with
four engines:
PIL
---
``'sorl.thumbnail.engines.pil_engine.Engine'``. This is the default engine
because it is what most people have installed already. Features:
* Easy to install
* Produces good quality images but not the best
* It is fast
* Can not handle CMYK sources
Pgmagick
--------
``'sorl.thumbnail.engines.pgmagick_engine.Engine'``. Pgmagick uses `Graphics
`_. Fatures:
* Not easy to install unless on linux, very slow to compile
* Produces high quality images
* It is a tad slow?
* Can handle CMYK sources
ImageMagick / GraphicsMagick
----------------------------
``'sorl.thumbnail.engines.convert_engine.Engine'``. This engine uses the
ImageMagick ``convert`` or GraphicsMagic ``gm convert`` command. Features:
* Easy to install
* Produces high quality images
* It is pretty fast
* Can handle CMYK sources
* It is a command line command, that is less than ideal,
Wand
----------------------------
``'sorl.thumbnail.engines.wand_engine.Engine'``. This engine uses `Wand
`_, a ctypes-based simple ImageMagick binding for Python.
Features:
* Easy to install
* Produces high quality images
* Can handle CMYK sources
* Works on Python 2.6, 2.7, 3.2, 3.3, and PyPy
``THUMBNAIL_CONVERT``
=====================
- Default ``'convert'``
Path to convert command, use ``'gm convert'`` for GraphicsMagick.
Only applicable for the convert Engine.
``THUMBNAIL_IDENTIFY``
======================
- Default ``'identify'``
Path to identify command, use ``'gm identify'`` for GraphicsMagick.
Only applicable for the convert Engine.
``THUMBNAIL_STORAGE``
=====================
- Default: ``settings.DEFAULT_FILE_STORAGE``
The storage class to use for the generated thumbnails.
``THUMBNAIL_REDIS_URL``
=======================
The Redis database URL to connect as used by `redis-py `_
When specified, other ``THUMBNAIL_REDIS_*`` connection settings will be ignored.
``THUMBNAIL_REDIS_DB``
======================
- Default: ``0``
The Redis database. Only applicable for the Redis Key Value Store
``THUMBNAIL_REDIS_PASSWORD``
============================
- Default: ``''``
The password for Redis server. Only applicable for the Redis Key Value Store
``THUMBNAIL_REDIS_HOST``
========================
- Default: ``'localhost'``
The host for Redis server. Only applicable for the Redis Key Value Store
``THUMBNAIL_REDIS_PORT``
========================
- Default: ``6379``
The port for Redis server. Only applicable for the Redis Key Value Store
``THUMBNAIL_REDIS_TIMEOUT``
===========================
- Default: ``3600 * 24 * 365 * 10``
Cache timeout for Redis Key Value Store in seconds. You should probably keep this
at maximum or ``None``.
``THUMBNAIL_DBM_FILE``
======================
- Default: ``thumbnail_kvstore``
Filename of the DBM database. Depending on the DBM engine selected by your
Python installation, this will be used as a prefix because multiple files may be
created. This can be an absolute path.
``THUMBNAIL_DBM_MODE``
======================
- Default: ``0x644``
Permission bits to use when creating new DBM files
``THUMBNAIL_CACHE_TIMEOUT``
===========================
- Default: ``3600 * 24 * 365 * 10``
Cache timeout for Cached DB Key Value Store in seconds. You should probably keep this
at maximum or ``None`` if your caching backend can handle that as infinite.
Only applicable for the Cached DB Key Value Store.
``THUMBNAIL_CACHE``
===================
- Default: ``'default'``
Cache configuration for Cached DB Key Value Store. Defaults to the ``'default'`` cache
but some applications might have multiple cache clusters.
``THUMBNAIL_KEY_PREFIX``
========================
- Default: ``'sorl-thumbnail'``
Key prefix used by the key value store.
``THUMBNAIL_PREFIX``
====================
- Default: ``'cache/'``
The generated thumbnails filename prefix.
``THUMBNAIL_FORMAT``
====================
- Default: ``'JPEG'``
Default image format, supported formats are: ``'JPEG'``, ``'PNG'``. This also implicitly
sets the filename extension. This can be overridden by individual options.
``THUMBNAIL_PRESERVE_FORMAT``
=============================
- Default: ``False``
If ``True``, the format of the input file will be preserved. If ``False``,
``THUMBNAIL_FORMAT`` will be used.
``THUMBNAIL_COLORSPACE``
========================
- Default: ``'RGB'``
Default thumbnail color space, engines are required to implement: ``'RGB'``,
``'GRAY'`` Setting this to None will keep the original color space. This can be
overridden by individual options.
``THUMBNAIL_UPSCALE``
=====================
- Default: ``True``
Should we upscale by default? ``True`` means we upscale images by default.
``False`` means we don't. This can be overridden by individual options.
``THUMBNAIL_QUALITY``
=====================
- Default: ``95``
Default thumbnail quality. A value between 0 and 100 is allowed. This can be
overridden by individual options.
``THUMBNAIL_PROGRESSIVE``
=========================
- Default: ``True``
Saves jpeg thumbnails as progressive jpegs. This can be overridden by individual
options.
``THUMBNAIL_ORIENTATION``
=========================
- Default: ``True``
Orientate the thumbnail with respect to source EXIF orientation tag
``THUMBNAIL_DUMMY``
===================
- Default: ``False``
This is a very powerful option which came from real world frustration. The use
case is when you want to do development on a deployed project that has image
references in its database. Instead of downloading all the image files from the
server hosting the deployed project and all its thumbnails we just set this
option to ``True``. This will generate placeholder images for all thumbnails
missing input source.
``THUMBNAIL_DUMMY_SOURCE``
==========================
- Default ``https://dummyimage.com/%(width)sx%(height)s``
This is the generated thumbnail whensource of the presented thumbnail. Width and
Height is passed to the string for formatting. Other options are for example:
- ``https://via.placeholder.com/%(width)sx%(height)s
- ``http://placekitten.com/%(width)s/%(height)s``
``THUMBNAIL_DUMMY_RATIO``
=========================
- Default: ``1.5``
This value sets an image ratio to all thumbnails that are not defined by width
**and** height since we cannot determine from the file input (since we don't
have that).
``THUMBNAIL_ALTERNATIVE_RESOLUTIONS``
=====================================
- Default: ``[]``
- Example: ``[1.5, 2]``
This value enables creation of additional high-resolution ("Retina") thumbnails
for every thumbnail. Resolution multiplicators, e.g. value 2 means for every thumbnail
of regular size x\*y, additional thumbnail of 2x\*2y size is created.
``THUMBNAIL_FILTER_WIDTH``
==========================
- Default: ``500``
This value sets the width of thumbnails inserted when running filters one texts
that regex replaces references to images with thumbnails.
``THUMBNAIL_URL_TIMEOUT``
=========================
- Default: ``None``
This value sets the timeout value in seconds when retrieving a source image from a URL.
If no timeout value is specified, it will wait indefinitely for a response.
``THUMBNAIL_REMOVE_URL_ARGS``
=============================
- Default: ``True``
This value sets if URL arguments will be removed from the source URL of the image we want to generate a thumbnail of. E.g. if our source image is at ``/picture?height=600&width=600`` a ``True`` value would instead attempt to generate a thumbnail from ``/picture``.
sorl-thumbnail-12.10.0/docs/requirements.rst 0000664 0000000 0000000 00000006346 14507342020 0021026 0 ustar 00root root 0000000 0000000 ************
Requirements
************
Base requirements
=================
- `Python`_ 3.8+
- `Django`_
- :ref:`kvstore-requirements`
- :ref:`image-library`
.. _kvstore-requirements:
Key Value Store
===============
sorl-thumbnail needs a Key Value Store for its operation. You can choose between
a **cached database** which requires no special installation to your normal
Django setup besides installing a proper cache like memcached **or** you can
setup **redis** which requires a little bit more work.
Cached DB
---------
All you need to use the cached database key value store is a database and `cache
`_ setup properly using
memcached. This cache needs to be really fast so **using anything else than
memcached is not recommended**.
Redis
-----
Redis is a fast key value store also suited for the job. To use the `redis`_ key
value store you first need to install the `redis server
`_. After that install the `redis client
`_::
pip install redis
.. _image-library:
Image Library
=============
You need to have an image library installed. sorl-thumbnail ships with support
for `Python Imaging Library`_, `pgmagick`_, `ImageMagick`_ (or `GraphicsMagick`)
command line tools. `pgmagick`_ are python bindings for `GraphicsMagick`_
(Magick++)`,
The `ImageMagick`_ based engine ``sorl.thumbnail.engines.convert_engine.Engine``
by default calls ``convert`` and ``identify`` shell commands. You can change the
paths to these tools by setting ``THUMBNAIL_CONVERT`` and ``THUMBNAIL_IDENTIFY``
respectively. Note that you need to change these to use `GraphicsMagick`_ to
``/path/to/gm convert`` and ``/path/to/gm identify``.
Python Imaging Library installation
-----------------------------------
Prerequisites:
- libjpeg
- zlib
Ubuntu 10.04 package installation::
sudo apt-get install libjpeg62 libjpeg62-dev zlib1g-dev
Installing `Python Imaging Library`_ using pip::
pip install Pillow
Watch the output for messages on what support got compiled in, you at least
want to see the following::
--- JPEG support available
--- ZLIB (PNG/ZIP) support available
pgmagick installation
---------------------
Prerequisites:
- GraphicsMagick
- Boost.Python
Ubuntu 10.04 package installation::
sudo apt-get install libgraphicsmagick++-dev
sudo apt-get install libboost-python1.40-dev
Fedora installation::
yum install GraphicsMagick-c++-devel
yum install boost-devel
Installing `pgmagick`_ using pip::
pip install pgmagick
ImageMagick installation
------------------------
Ubuntu 10.04 package installation::
sudo apt-get install imagemagick
Or if you prefer `GraphicsMagick`_::
sudo apt-get install graphicsmagick
Wand installation
------------------------
Ubuntu installation::
apt-get install libmagickwand-dev
pip install Wand
.. _Python Imaging Library: https://python-pillow.org/
.. _ImageMagick: https://imagemagick.org/
.. _GraphicsMagick: http://www.graphicsmagick.org/
.. _redis: https://redis.io/
.. _redis-py: https://github.com/redis/redis-py
.. _Django: https://www.djangoproject.com/
.. _Python: https://www.python.org/
.. _pgmagick: https://pgmagick.readthedocs.io/
.. _wand: https://docs.wand-py.org
sorl-thumbnail-12.10.0/docs/template.rst 0000664 0000000 0000000 00000022057 14507342020 0020113 0 ustar 00root root 0000000 0000000 *************************
Template tags and filters
*************************
.. highlight:: html+django
Sorl-thumbnail comes with one template tag `thumbnail`_ and three filters:
`is_portrait`_, `margin`_ and `resolution`_. To use any of them in you
templates you first need to load them::
{% load thumbnail %}
.. _thumbnail:
thumbnail
=========
Syntax::
{% thumbnail source geometry [key1=value1, key2=value2...] as var %}
{% endthumbnail %}
Alternative syntax using empty::
{% thumbnail source geometry [key1=value1, key2=value2...] as var %}
{% empty %}
{% endthumbnail %}
The ``{% empty %}`` section is rendered if the thumbnail source is resolved to
an empty value or an invalid image source, you can think of it as rendering
when the thumbnail becomes undefined.
.. _source:
Source
------
.. highlight:: python
Source can be an ImageField, FileField, a file name (assuming default_storage),
a url. What we need to know is name and storage, see how ImageFile figures
these things out::
from django.utils.encoding import force_str
class ImageFile(BaseImageFile):
_size = None
def __init__(self, file_, storage=None):
if not file_:
raise ThumbnailError('File is empty.')
# figure out name
if hasattr(file_, 'name'):
self.name = file_.name
else:
self.name = force_str(file_)
# figure out storage
if storage is not None:
self.storage = storage
elif hasattr(file_, 'storage'):
self.storage = file_.storage
elif url_pat.match(self.name):
self.storage = UrlStorage()
else:
self.storage = default_storage
Geometry
--------
.. highlight:: html+django
Geometry is specified as ``widthxheight``, ``width`` or ``xheight``.
Width and height are in pixels. Geometry can either be a string or resolve
into a valid geometry string. Examples::
{% thumbnail item.image "200x100" as im %}
{% endthumbnail %}
{% thumbnail item.image "200" as im %}
{% endthumbnail %}
{% thumbnail item.image "x100" as im %}
{% endthumbnail %}
{% thumbnail item.image geometry as im %}
{% endthumbnail %}
If width and height are given the image is rescaled to maximum values of height
and width given. Aspect ratio preserved.
Options
-------
Options are passed on to the backend and engine, the backend generates the
thumbnail filename from it and the engine can use it for processing. Option
keys are not resolved in context but values are. Passing all options to the
engine means that you can easily subclass an engine and create new features
like rounded corners or what ever processing you like. The options described
below are how they are used and interpreted in the shipped engines.
``cropbox``
^^^^^^^^^^^
This option is used to crop to a specific set of coordinates. ``cropbox`` takes
``x, y, x2, y2`` as arguments to crop the image down via those set of coordinates.
Note that ``cropbox`` is applied before ``crop``.
.. code-block:: python
img = get_thumbnail(sorl_img, cropbox="{0},{1},{2},{3}".format(
x, y, x2, y2))
``crop``
^^^^^^^^
This option is only used if both width and height is given. Crop behaves much
like `css background-position`_. The image is first rescaled to minimum values
of height and width given, this will be equivalent to the `padding box` in the
above text. After it is rescaled it will apply the cropping options. There are
some differences to the `css background-position`_:
- Only % and px are valid lengths (units)
- ``noop`` (No Operation) is a valid option which means there is no
cropping after the initial rescaling to minimum of width and height.
There are many overlapping options here for example ``center`` is equivalent to
``50%``. There is not a problem with that in it self but it is a bit of a
problem if you will for sorl-thumbnail. Sorl-thumbnail will generate a new
thumbnail for every unique source, geometry and options. This is a design
choice because we want to stay flexible with the options and not interpret them
anywhere else but in the engine methods. In clear words, be consistent in your
cropping options if you don't want to generate unnecessary thumbnails. In case
you are wondering, sorl-thumbnail sorts the options so the order does not
matter, same options but in different order will generate only one thumbnail.
``upscale``
^^^^^^^^^^^
Upscale is a boolean and controls if the image can be upscaled or not. For
example if your source is 100x100 and you request a thumbnail of size 200x200
and upscale is False this will return a thumbnail of size 100x100. If upscale
was True this would result in a thumbnail size 200x200 (upscaled). The default
value is ``True``.
``quality``
^^^^^^^^^^^
Quality is a value between 0-100 and controls the thumbnail write quality.
Default value is ``95``.
``progressive``
^^^^^^^^^^^^^^^
This controls whether to save jpeg thumbnails as progressive jpegs. Default
value is ``True``.
``orientation``
^^^^^^^^^^^^^^^
This controls whether to orientate the resulting thumbnail with respect to the
source EXIF tags for orientation. Default value is ``True``.
``format``
^^^^^^^^^^
This controls the write format and thumbnail extension. Formats supported by
the shipped engines are ``'JPEG'`` and ``'PNG'``. Default value is ``'JPEG'``.
``colorspace``
^^^^^^^^^^^^^^
This controls the resulting thumbnails color space, valid values are: ``'RGB'``
and ``'GRAY'``. Default value is ``'RGB'``.
``padding``
^^^^^^^^^^^
Padding is a boolean and controls if the image should be padded to fit the
specified geometry.
If your image is ``200x100``::
{% thumbnail image "100x100" padding=True as im %}
``im`` will be ``100x100`` with white padding at the top and bottom. The color
of the padding can be controlled with ``padding_color`` or the setting
``THUMBNAIL_PADDING_COLOR`` which defaults to ``#ffffff``.
Images are not padded by default, but this can be changed by setting
``THUMBNAIL_PADDING`` to ``True``.
``padding_color``
^^^^^^^^^^^^^^^^^
This is the color to use for padding the image. It defaults to ``#ffffff`` and
can be globally set with the setting ``THUMBNAIL_PADDING_COLOR``.
``options``
^^^^^^^^^^^
Yes this option is called ``options``. This needs to be a context variable that
resolves to a dictionary. This dictionary can contain multiple options, for
example::
options = {'colorspace': 'GRAY', 'quality': 75, 'crop': 'center'}
You can use this option together with the other options but beware that the
order will matter. As soon as the keyword ``options`` is encountered all the
options that have a key in ``options`` are overwritten. Similarly, options in
the ``options`` dict will be overwritten by options set after the options
keyword argument to the thumbnail tag.
is_portrait
===========
This filter returns True if the image height is larger than the image width.
Examples::
{% thumbnail item.image "100x100" %}
{% if item.image|is_portrait %}
{% else %}
{% endif %}
{% endthumbnail %}
{% if item.image|is_portrait %}
{% thumbnail item.image "100x200" crop="center" %}
{% endthumbnail %}
{% else %}
{% thumbnail item.image "200x100" crop="center" %}
{% endthumbnail %}
{% endif %}
margin
======
Margin is a filter for calculating margins against a padding box. For example
lets say you have an image ``item.image`` and you want to pad it vertically in
a 1000x1000 box, you would simply write::
The above is a rather synthetic example the more common use case is when you want
boxes of images of a certain size but you do not want to crop them::
{% for profile in profiles %}
{% thumbnail profile.photo "100x100" as im %}
{% empty %}
{% endthumbnail %}
{% enfor %}
The more problematic is to get the top margin, however the margin filter
outputs all values.
.. _css background-position: https://www.w3.org/TR/CSS2/colors.html#propdef-background-position
resolution
==========
Resolution is a filter for obtaining alternative resolution versions of the
thumbnail. Your provided resolution must be one of the
``THUMBNAIL_ALTERNATIVE_RESOLUTIONS`` settings values (default: no alternative resolutions)
For example, let's say you have an image ``item.image`` and you want to
get the 2x DPI version of it. You would simply write::
sorl-thumbnail-12.10.0/setup.cfg 0000664 0000000 0000000 00000001570 14507342020 0016434 0 ustar 00root root 0000000 0000000 [bdist_wheel]
universal = 0
;; flake8 analyzes and detect varios errors in the source code.
[flake8]
# D105 - Missing docstring in magic method `__func__`
ignore = D105,W503
max-line-length = 100
exclude = .git,
.tox,
docs/*,
*/migrations/*,
tests/settings/*,
sorl/thumbnail/__init__.py,
sorl/thumbnail/admin/__init__.py
max_complexity = 15
;; Coverage.py, Code coverage testing for Python.
[cov:run]
source = sorl
omit = */sorl-thumbnail/sorl/__init__.py
*/sorl/thumbnail/__init__.py
*/sorl/thumbnail/conf/__init__.py
*/sorl/thumbnail/admin/__init__.py
[cov:report]
exclude_lines = pragma: no cover
if __name__ == .__main__.:
;; The pytest framework
[tool:pytest]
python_files = test_*.py *tests.py
norecursedirs = .* tmp* __pycache__
testpaths = tests
django_find_project = false
sorl-thumbnail-12.10.0/setup.py 0000664 0000000 0000000 00000002515 14507342020 0016325 0 ustar 00root root 0000000 0000000 from setuptools import setup, find_packages
setup(
name='sorl-thumbnail',
use_scm_version=True,
description='Thumbnails for Django',
long_description=open('README.rst').read(),
author="Mikko Hellsing",
author_email='mikko@aino.se',
maintainer="Jazzband",
maintainer_email="roadies@jazzband.co",
license="BSD",
url='https://github.com/jazzband/sorl-thumbnail',
packages=find_packages(exclude=['tests', 'tests.*']),
platforms='any',
python_requires='>=3.8',
zip_safe=False,
classifiers=[
'Development Status :: 5 - Production/Stable',
'Environment :: Web Environment',
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
'Topic :: Multimedia :: Graphics',
'Framework :: Django',
'Framework :: Django :: 3.2',
'Framework :: Django :: 4.0',
'Framework :: Django :: 4.1',
'Framework :: Django :: 4.2',
],
setup_requires=['setuptools_scm'],
)
sorl-thumbnail-12.10.0/sorl/ 0000775 0000000 0000000 00000000000 14507342020 0015567 5 ustar 00root root 0000000 0000000 sorl-thumbnail-12.10.0/sorl/__init__.py 0000664 0000000 0000000 00000000264 14507342020 0017702 0 ustar 00root root 0000000 0000000 from importlib.metadata import version, PackageNotFoundError
try:
__version__ = version("sorl-thumbnail")
except PackageNotFoundError:
# package is not installed
pass
sorl-thumbnail-12.10.0/sorl/thumbnail/ 0000775 0000000 0000000 00000000000 14507342020 0017552 5 ustar 00root root 0000000 0000000 sorl-thumbnail-12.10.0/sorl/thumbnail/__init__.py 0000664 0000000 0000000 00000000151 14507342020 0021660 0 ustar 00root root 0000000 0000000 from sorl.thumbnail.fields import ImageField
from sorl.thumbnail.shortcuts import get_thumbnail, delete
sorl-thumbnail-12.10.0/sorl/thumbnail/admin/ 0000775 0000000 0000000 00000000000 14507342020 0020642 5 ustar 00root root 0000000 0000000 sorl-thumbnail-12.10.0/sorl/thumbnail/admin/__init__.py 0000664 0000000 0000000 00000000224 14507342020 0022751 0 ustar 00root root 0000000 0000000 from django.forms import ClearableFileInput
from .current import AdminImageMixin
AdminInlineImageMixin = AdminImageMixin # backwards compatibility
sorl-thumbnail-12.10.0/sorl/thumbnail/admin/current.py 0000664 0000000 0000000 00000004257 14507342020 0022706 0 ustar 00root root 0000000 0000000 import logging
from django import forms
from django.utils.safestring import mark_safe
from sorl.thumbnail.fields import ImageField
from sorl.thumbnail.shortcuts import get_thumbnail
logger = logging.getLogger(__name__)
class AdminImageWidget(forms.ClearableFileInput):
"""
An ImageField Widget for django.contrib.admin that shows a thumbnailed
image as well as a link to the current one if it hase one.
"""
template_with_initial = (
'%(clear_template)s '
''
)
template_with_clear = ''
def render(self, name, value, attrs=None, **kwargs):
output = super().render(name, value, attrs, **kwargs)
if value and hasattr(value, 'url'):
ext = 'JPEG'
try:
aux_ext = str(value).split('.')
if aux_ext[len(aux_ext) - 1].lower() == 'png':
ext = 'PNG'
elif aux_ext[len(aux_ext) - 1].lower() == 'gif':
ext = 'GIF'
except Exception:
pass
try:
mini = get_thumbnail(value, 'x80', upscale=False, format=ext)
except Exception as e:
logger.warning("Unable to get the thumbnail", exc_info=e)
else:
try:
output = (
'