A drop-in replacement for django's ImageField that provides a flexible, intuitive and easily-extensible interface for quickly creating new images from the one assigned to the field.

Overview

django-versatileimagefield

Github Actions Status Coverage Status Latest Version

A drop-in replacement for django's ImageField that provides a flexible, intuitive and easily-extensible interface for creating new images from the one assigned to the field.

Click here for a quick overview of what it is, how it works and whether or not it's the right fit for your project.

Compatibility

  • Python:
    • 3.6
    • 3.7
    • 3.8
    • 3.9
  • Django:
    • 2.0.x
    • 2.1.x
    • 2.2.x
    • 3.0.x
    • 3.1.x
    • 3.2.x

NOTE: Python 3.6 does not have support for Django <= 1.x.

NOTE: The 1.4 release dropped support for Django 1.5.x & 1.6.x.

NOTE: The 1.7 release dropped support for Django 1.7.x.

NOTE: The 2.1 release dropped support for Django 1.9.x.

Documentation

Full documentation available at Read the Docs.

Code

django-versatileimagefield is hosted on github.

Running Tests

If you're running tests on Mac OSX you'll need libmagic installed. The recommended way to do this is with homebrew:

$ brew install libmagic

Note: Some systems may also be necessary to install the non-python Pillow build dependencies.

You'll also need tox:

$ pip install tox

To run the entire django-versatileimagefield test matrix, that is, run all tests on all supported combination of versions of python, django and djangorestframework:

$ tox

If you just want to run tests against a specific tox environment first, run this command to list all available environments:

$ tox -l

Then run this command, substituting {tox-env} with the environment you want to test:

$ tox -e {tox-env}
Comments
  • Trying to get this to work with django-storages

    Trying to get this to work with django-storages

    I'm using Google Cloud Storage to serve up images.

    class PhotoSerializer(serializers.ModelSerializer, TaggitSerializer):
        owner = serializers.CharField(source='owner.username', read_only=True)
        tags = TagListSerializerField()
        photo = VersatileImageFieldSerializer(
             sizes=[
                ('full_size', 'url'),
                ('thumbnail', 'thumbnail__250x250')
            ]
        )
    

    When I try to upload images from my front end, I am getting errors like this:

    google.cloud.exceptions.NotFound: 404 File does not exist: __sized__/img/u/1/pexels-photo-thumbnail-250x250-70.jpg

    opened by EvanZ 12
  • Support WEBP sizers and filters

    Support WEBP sizers and filters

    Adding support for WEBP resizing. This is an issue presented by some users and happened with me. Currently, trying to resize WEBP images results in some errors. This PR fixes them.

    Fixes #151

    opened by iamjazzar 11
  • Fixed usage with cloud storage backends

    Fixed usage with cloud storage backends

    Some (all?) cloud storage backends won't provide a URL for a file that doesn't yet exist. This fixes that but attempting to get a resized_url, but if it fails, we create the resized_image first, and then grab it's url.

    opened by camflan 11
  • Still show the widget even if thumbnailing fails/crashes

    Still show the widget even if thumbnailing fails/crashes

    When an image is not uploaded completely the sizers crash. This has been discussed several times before (resp. crashes when the image file does not exist etc.), and fixes have been rejected. (I do not fully agree with the resolution, but that's not the point of this pull request.)

    However, it should still be possible to remove or replace these files again. The current implementation which calls .thumbnail['300x300'] prevents this by causing the whole fieldset containing the versatile image field admin widget to disappear.

    opened by matthiask 11
  • Cleaner processed filenames using hash of options?

    Cleaner processed filenames using hash of options?

    We would like to cleanup the generated thumbnail paths/filenames.

    By default DVIF will generate a long concatenation of all the filters and parameters used to generate the image in a human readable but a little messy looking URL (many segments with double underscores, numbers, dots and dashes). Since some of our image URL's are somewhat visible to our users we'd like to clean this up if possible.

    Our existing thumbnailer (an old easythumbnails hackjob) also did this, but we've added a simple hashing function that takes the options concatenation and hashes it to make a compact chunky block of characters.

    Because it uses a hashing function it is still generating unique names for each combination of options.

    // so instead of something like this:
    thumbs/images/foo-desaturate__75__fancify-0-7__1-23-crop-c0-75__0-25-400x400.jpg
    
    // get something like this
    thumbs/images/foo-ff8765ab-400x400.jpg
    

    In our existing site we use an md5 binary hash encoded in (crockford) base32 alphabet and trimmed for length. These are fairly compact string (unlike hex) but non-scary (no casing or specials chars).

    Maybe DVIF could provide an option to have the user supply a hashing function like this? Could be a simple dot-separated path to an importable callback so people can bring their own hashers.

    opened by Bartvds 11
  • delete_sized_images() fails with custom upload_to

    delete_sized_images() fails with custom upload_to

    I have a custom upload_to path:

    def file_name(instance, path):
        filename = os.path.basename(path)
        sepFilename = os.path.splitext(filename)
        newFilename = slugify(sepFilename[0]) + sepFilename[1]
        year = str(instance.album.year)
        album_slug = instance.album.slug
    
        return '/'.join([year, album_slug, newFilename])
    
    #...
    
    class Image(BaseMedia):
        file = VersatileImageField(upload_to=file_name)
        #...
    

    When I run delete_sized_images() the files are not deleted. The problem is the custom path is both appended by get_sized_root_folder() and prepended by sizer_regex.

    Example:

    def delete_sized_images(self):
        #...
        print(self.get_sized_root_folder()) # __sized__/2015/sd/
        print(self.sizer_regex.pattern)     # 2015/sd/g0043229-(thumbnail|crop)-(\d+)x(\d+)(?:-\d+)?.JPG
        #...
    

    Thank you for your time.

    opened by neic 8
  • ValueError at ... The file cannot be reopened.

    ValueError at ... The file cannot be reopened.

    I'm using PPOIField, but when I save (using the admin) an exception is raised in /versatileimagefield/forms.py when data.open() is called.

    My images are saved from external urls to s3, maybe this info and this link are useful.

    Django==1.8.11
    boto==2.39.0
    django-s3-storage==0.9.8
    django-versatileimagefield==1.3
    
    opened by fabiocaccamo 8
  • Image format conversions

    Image format conversions

    Hi, we're using versatile image field to feed a PWA. We'd like to be able to provide images in different formats as well. For example, browsers that support webp would request the images in webp, while primitive ones like Safari can fall back to png.

    We'd like to know if this is achievable through custom sizers and filters. If so, could you give us a simple example?

    Our plan B is to use PIL to generate multiple formats on upload. The different formats are then saved each in a versatile image field. For this to work, we'll need to know what image formats are supported. WebP doesn't seem to appear in the list here for example https://django-versatileimagefield.readthedocs.io/en/latest/writing_custom_sizers_and_filters.html#pre-processor-naming-convention

    opened by khalibloo 7
  • Remove deprecation warning on Django 2.0 and newer

    Remove deprecation warning on Django 2.0 and newer

    Latest Pytest throws deprecation warnings into the console, this PR gets rid of one of them. context keyword argument of from_db_value was dropped in Django 2.0 and will be deprecated in Django 3.0

    opened by Pacu2 7
  • ValueError in django/forms/fields.py when editing an Object that uses VersatileImageField

    ValueError in django/forms/fields.py when editing an Object that uses VersatileImageField

    Django raises an ValueError when I edit an object which uses the VersatileImageField. Creating the object is no problem. Whether the VersatileImageField uses a ppoi or not does not matter. Switching back to the default ImageField solves the problem. I also removed the cache settings in VERSATILEIMAGEFIELD_SETTINGS (does that actually deactivate the cache?)

    Django Version: 1.7 Python Version: 2.7.6 Installed Applications:

    ('django.contrib.admin',
     'django.contrib.auth',
     'django.contrib.contenttypes',
     'django.contrib.sessions',
     'django.contrib.messages',
     'django.contrib.staticfiles',
     'core',
     'versatileimagefield')
    

    Installed Middleware:

    ('django.contrib.sessions.middleware.SessionMiddleware',
     'django.middleware.common.CommonMiddleware',
     'django.middleware.csrf.CsrfViewMiddleware',
     'django.contrib.auth.middleware.AuthenticationMiddleware',
     'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
     'django.contrib.messages.middleware.MessageMiddleware',
     'django.middleware.clickjacking.XFrameOptionsMiddleware')
    

    Traceback:

    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
      111.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/contrib/admin/options.py" in wrapper
      567.                 return self.admin_site.admin_view(view)(*args, **kwargs)
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapped_view
      105.                     response = view_func(request, *args, **kwargs)
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
      52.         response = view_func(request, *args, **kwargs)
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/contrib/admin/sites.py" in inner
      204.             return view(request, *args, **kwargs)
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/contrib/admin/options.py" in change_view
      1440.         return self.changeform_view(request, object_id, form_url, extra_context)
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapper
      29.             return bound_func(*args, **kwargs)
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapped_view
      105.                     response = view_func(request, *args, **kwargs)
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/utils/decorators.py" in bound_func
      25.                 return func.__get__(self, type(self))(*args2, **kwargs2)
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/db/transaction.py" in inner
      394.                 return func(*args, **kwargs)
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/contrib/admin/options.py" in changeform_view
      1394.                     change_message = self.construct_change_message(request, form, formsets)
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/contrib/admin/options.py" in construct_change_message
      972.         if form.changed_data:
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/forms/forms.py" in changed_data
      440.                 elif field._has_changed(initial_value, data_value):
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/forms/fields.py" in _has_changed
      1082.             if field._has_changed(field.to_python(initial), data):
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/forms/fields.py" in to_python
      652.                 file = BytesIO(data.read())
    
    Exception Type: ValueError at /admin/core/cinema/1/
    Exception Value: I/O operation on closed file
    
    opened by gregorvolkmann 7
  • Django 3 doesn't contain 'six' anymore

    Django 3 doesn't contain 'six' anymore

    See https://docs.djangoproject.com/en/3.0/releases/3.0/#removed-private-python-2-compatibility-apis

      File "/home/tic/Development/karrot-docker/karrot-backend/karrot/groups/models.py", line 13, in <module>
        from versatileimagefield.fields import VersatileImageField
      File "/home/tic/Development/karrot-docker/karrot-backend/env/lib/python3.7/site-packages/versatileimagefield/fields.py", line 12, in <module>
        from .files import VersatileImageFieldFile, VersatileImageFileDescriptor
      File "/home/tic/Development/karrot-docker/karrot-backend/env/lib/python3.7/site-packages/versatileimagefield/files.py", line 9, in <module>
        from django.utils import six
    ImportError: cannot import name 'six' from 'django.utils' (/home/tic/Development/karrot-docker/karrot-backend/env/lib/python3.7/site-packages/django/utils/__init__.py)
    
    opened by tiltec 6
  • Question: Crop as circle

    Question: Crop as circle

    Hi, is there a possibility to make a circle version of a image, it will be really usefull when u work with agm-map directive on angular and u dont have control about the image icon.

    opened by breakiboy 0
  • Deleted unnecessary default_app_config settings starting with django3.2

    Deleted unnecessary default_app_config settings starting with django3.2

    Warning problem solving python3.9/site-packages/django/apps/registry.py:91: RemovedInDjango41Warning: 'versatileimagefield' defines default_app_config = 'versatileimagefield.apps.VersatileImageFieldConfig'. Django now detects this configuration automatically. You can remove default_app_config.

    opened by LeeHanYeong 0
  • Question: is it possible to use this app with static files?

    Question: is it possible to use this app with static files?

    Hi all,

    this is a question, not an issue. Is it possible to use this app with static files?

    Something like generating thumbnail from a file path.

    Thank you

    opened by carlotm 0
  • VersatileImageFieldWarmer regenerate images for delete rendition key set

    VersatileImageFieldWarmer regenerate images for delete rendition key set

    Image are initially created with proper rendition key set.

    warmer = VersatileImageFieldWarmer(
                            instance_or_queryset=queryset,
                            rendition_key_set=[('large_horiz', 'crop__1200x600')],
                            image_attr=field,
                            verbose=True,
                        )
    warmer.warm()                  
    

    Then, when rendition set sized images are deleted from media/__sized__/ re-running warm doesn't create new image but if we change rendition_key_set to rendtion_key_set=[[('large_horiz', 'crop__1250x600')] images are created. Even when we run delete_sized_images, delete_all_created_images, delete_filtered_images, delete_filtered_sized_images and delete_sized_images. Images are not regenerated

    opened by roshanshrestha01 0
  • Deleting all created images for the image without extension fails

    Deleting all created images for the image without extension fails

    When trying to delete all created images with the use of delete_all_created_images method I get the AssertionError. I find out that the sized images are created with extension jpg when the base image is without extension. It causes an error during deletion as the algorithm is looking for a file with the same extension as the base one.

    Steps to reproduce:

    1. Save in VersatileImageField file without extension in the name.
    2. Create some thumbnails.
    3. Try to remove all created images with the use of delete_all_created_images.
    4. You will get the AssertionError.
    opened by IKarbowiak 0
MAC address Model Field & Form Field for Django apps

django-macaddress MAC Address model and form fields for Django We use netaddr to parse and validate the MAC address. The tests aren't complete yet. Pa

null 49 Sep 4, 2022
A Django application that provides country choices for use with forms, flag icons static files, and a country field for models.

Django Countries A Django application that provides country choices for use with forms, flag icons static files, and a country field for models. Insta

Chris Beaven 1.2k Jan 7, 2023
A Django application that provides country choices for use with forms, flag icons static files, and a country field for models.

Django Countries A Django application that provides country choices for use with forms, flag icons static files, and a country field for models. Insta

Chris Beaven 1.2k Dec 31, 2022
The best way to have DRY Django forms. The app provides a tag and filter that lets you quickly render forms in a div format while providing an enormous amount of capability to configure and control the rendered HTML.

django-crispy-forms The best way to have Django DRY forms. Build programmatic reusable layouts out of components, having full control of the rendered

null 4.6k Jan 7, 2023
Location field and widget for Django. It supports Google Maps, OpenStreetMap and Mapbox

django-location-field Let users pick locations using a map widget and store its latitude and longitude. Stable version: django-location-field==2.1.0 D

Caio Ariede 481 Dec 29, 2022
Tweak the form field rendering in templates, not in python-level form definitions. CSS classes and HTML attributes can be altered.

django-widget-tweaks Tweak the form field rendering in templates, not in python-level form definitions. Altering CSS classes and HTML attributes is su

Jazzband 1.8k Jan 2, 2023
A django model and form field for normalised phone numbers using python-phonenumbers

django-phonenumber-field A Django library which interfaces with python-phonenumbers to validate, pretty print and convert phone numbers. python-phonen

Stefan Foulis 1.3k Dec 31, 2022
A django model and form field for normalised phone numbers using python-phonenumbers

django-phonenumber-field A Django library which interfaces with python-phonenumbers to validate, pretty print and convert phone numbers. python-phonen

Stefan Foulis 1.3k Dec 31, 2022
Django project starter on steroids: quickly create a Django app AND generate source code for data models + REST/GraphQL APIs (the generated code is auto-linted and has 100% test coverage).

Create Django App ?? We're a Django project starter on steroids! One-line command to create a Django app with all the dependencies auto-installed AND

imagine.ai 68 Oct 19, 2022
A reusable Django model field for storing ad-hoc JSON data

jsonfield jsonfield is a reusable model field that allows you to store validated JSON, automatically handling serialization to and from the database.

Ryan P Kilby 1.1k Jan 3, 2023
Custom Django field for using enumerations of named constants

django-enumfield Provides an enumeration Django model field (using IntegerField) with reusable enums and transition validation. Installation Currently

5 Monkeys 195 Dec 20, 2022
A pickled object field for Django

django-picklefield About django-picklefield provides an implementation of a pickled object field. Such fields can contain any picklable objects. The i

Gintautas Miliauskas 167 Oct 18, 2022
A pickled object field for Django

django-picklefield About django-picklefield provides an implementation of a pickled object field. Such fields can contain any picklable objects. The i

Gintautas Miliauskas 167 Oct 18, 2022
Resolve form field arguments dynamically when a form is instantiated

django-forms-dynamic Resolve form field arguments dynamically when a form is instantiated, not when it's declared. Tested against Django 2.2, 3.2 and

DabApps 108 Jan 3, 2023
Cookiecutter Django is a framework for jumpstarting production-ready Django projects quickly.

Cookiecutter Django Powered by Cookiecutter, Cookiecutter Django is a framework for jumpstarting production-ready Django projects quickly. Documentati

Daniel Feldroy 10k Dec 31, 2022
Django-fast-export - Utilities for quickly streaming CSV responses to the client

django-fast-export Utilities for quickly streaming CSV responses to the client T

Matthias Kestenholz 4 Aug 24, 2022
Organize Django settings into multiple files and directories. Easily override and modify settings. Use wildcards and optional settings files.

Organize Django settings into multiple files and directories. Easily override and modify settings. Use wildcards in settings file paths and mark setti

Nikita Sobolev 940 Jan 3, 2023
django-tables2 - An app for creating HTML tables

django-tables2 - An app for creating HTML tables django-tables2 simplifies the task of turning sets of data into HTML tables. It has native support fo

Jan Pieter Waagmeester 1.6k Jan 3, 2023
Django-discord-bot - Framework for creating Discord bots using Django

django-discord-bot Framework for creating Discord bots using Django Uses ASGI fo

Jamie Bliss 1 Mar 4, 2022