Code Monkey home page Code Monkey logo

django-versatileimagefield's Introduction

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:
    • 3.0.x
    • 3.1.x
    • 3.2.x
    • 4.0.x
    • 4.1.x
    • 5.0.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.

NOTE: The 3.0 release dropped support for Django 2.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}

django-versatileimagefield's People

Contributors

aleksihakli avatar bogdal avatar browniebroke avatar camflan avatar chubz avatar derenio avatar dmptrluke avatar fabiocaccamo avatar gbts avatar hussam-almarzoq avatar iamjazzar avatar jelko avatar jxltom avatar luzfcb avatar matthiask avatar mortal avatar njamaleddine avatar nyankiyoshi avatar pacu2 avatar respondcreate avatar sannykr avatar sebcorbin avatar slurms avatar szewczykmira avatar timgates42 avatar topiaruss avatar tsotnesharvadze avatar tuky avatar vikrant-fueled avatar zadazorg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-versatileimagefield's Issues

collectstatic fails when using placeholders

Deploying a application using django-versatileimagefield to Heroku and S3 fails for a odd reason. Django's collectstatic (which is supposed to put the static files on to the storage - here S3) fails because django-versatileimagefield's placeholder_image=OnStoragePlaceholderImage(...) tries to access a image on the same storage. Obviously that is not there yet (since it is just in the process of putting the files there).

The issue seems to be that the the placeholder image gets accessed when Python is creating the classes (in the beginning of collectstatic). Instead it should possibly use some kind of lazy reference to the image which just accesses the file on disk when it is actively called.

$ python manage.py collectstatic

Traceback (most recent call last):
  File "manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/app/.heroku/python/lib/python2.7/site-packages/django/core/management/__init__.py", line 338, in execute_from_command_line
    utility.execute()
  File "/app/.heroku/python/lib/python2.7/site-packages/django/core/management/__init__.py", line 312, in execute
    django.setup()
  File "/app/.heroku/python/lib/python2.7/site-packages/django/__init__.py", line 18, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "/app/.heroku/python/lib/python2.7/site-packages/django/apps/registry.py", line 108, in populate
    app_config.import_models(all_models)
  File "/app/.heroku/python/lib/python2.7/site-packages/django/apps/config.py", line 198, in import_models
    self.models_module = import_module(models_module_name)
  File "/app/.heroku/python/lib/python2.7/importlib/__init__.py", line 37, in import_module
    __import__(name)
  File "/app/core/unchained_auth/models.py", line 6, in <module>
    from core.unchained_profiles.models import BaseProfile
  File "/app/core/unchained_profiles/models.py", line 29, in <module>
    class Employer(models.Model):
  File "/app/core/unchained_profiles/models.py", line 43, in Employer
    path=os.path.join('images', 'placeholder_company.png'), storage=StaticFilesStorage()
  File "/app/.heroku/python/lib/python2.7/site-packages/versatileimagefield/placeholder.py", line 57, in __init__
    file = storage.open(path)
  File "/app/.heroku/python/lib/python2.7/site-packages/django/core/files/storage.py", line 37, in open
    return self._open(name, mode)
  File "/app/.heroku/python/lib/python2.7/site-packages/storages/backends/s3boto.py", line 366, in _open
    raise IOError('File does not exist: %s' % name)
IOError: File does not exist: static/images/placeholder_company.png

Add libopenjpeg-dev fix to docs (ZeroDivisionError: division by zero)

At datastructures/base.py#L77

File "/www/gkk-package/local/lib/python2.7/site-packages/django/forms/forms.py" in as_widget
  593.         return force_text(widget.render(name, self.value(), attrs=attrs))
File "/www/gkk-package/local/lib/python2.7/site-packages/versatileimagefield/widgets.py" in render
  204.             attrs
File "/www/gkk-package/local/lib/python2.7/site-packages/django/forms/widgets.py" in render
  826.             output.append(widget.render(name + '_%s' % i, widget_value, final_attrs))
File "/www/gkk-package/local/lib/python2.7/site-packages/versatileimagefield/widgets.py" in render
  121.                 value
File "/www/gkk-package/local/lib/python2.7/site-packages/versatileimagefield/widgets.py" in image_preview
  87.             'sized_url': value.thumbnail['300x300'],
File "/www/gkk-package/local/lib/python2.7/site-packages/versatileimagefield/datastructures/sizedimage.py" in __getitem__
  116.                             height=height
File "/www/gkk-package/local/lib/python2.7/site-packages/versatileimagefield/datastructures/sizedimage.py" in create_resized_image
  184.         image, save_kwargs = self.preprocess(image, image_format)
File "/www/gkk-package/local/lib/python2.7/site-packages/versatileimagefield/datastructures/base.py" in preprocess
  75.             exif_datadict = image._getexif()  # returns None if no EXIF data
File "/www/gkk-package/local/lib/python2.7/site-packages/PIL/JpegImagePlugin.py" in _getexif
  391.         return _getexif(self)
File "/www/gkk-package/local/lib/python2.7/site-packages/PIL/JpegImagePlugin.py" in _getexif
  425.         exif.update(info)
File "/www/gkk-package/local/lib/python2.7/site-packages/PIL/TiffImagePlugin.py" in __getitem__
  354.             self[tag] = handler(self, data, self.legacy_api)  # check type
File "/www/gkk-package/local/lib/python2.7/site-packages/PIL/TiffImagePlugin.py" in load_rational
  484.                      for num, denom in zip(vals[::2], vals[1::2]))
File "/www/gkk-package/local/lib/python2.7/site-packages/PIL/TiffImagePlugin.py" in <genexpr>
  484.                      for num, denom in zip(vals[::2], vals[1::2]))
File "/www/gkk-package/local/lib/python2.7/site-packages/PIL/TiffImagePlugin.py" in <lambda>
  482.         combine = lambda a, b: (a, b) if legacy_api else a / b

Exception Type: ZeroDivisionError at /admin/product/product/2188/
Exception Value: division by zero

pip install fails for 0.3

Here is my installation error log for 0.3. Seems something to do with requirements.txt'. Installation succeeds for v0.2.1.

Downloading/unpacking django-versatileimagefield==0.3 (from -r requirements/common.txt (line 20))
  Using download cache from /Users/theskumar/Library/Caches/pip-downloads/https%3A%2F%2Fpypi.python.org%2Fpackages%2Fsource%2Fd%2Fdjango-versatileimagefield%2Fdjango-versatileimagefield-0.3.tar.gz
  Running setup.py (path:/Users/theskumar/work/pr/myproject/venv/build/django-versatileimagefield/setup.py) egg_info for package django-versatileimagefield
    Traceback (most recent call last):
      File "<string>", line 17, in <module>
      File "/Users/theskumar/work/pr/myproject/venv/build/django-versatileimagefield/setup.py", line 22, in <module>
        for ir in parse_requirements('requirements.txt')
      File "/Users/theskumar/work/pr/myproject/venv/lib/python2.7/site-packages/pip/req.py", line 1546, in parse_requirements
        session=session,
      File "/Users/theskumar/work/pr/myproject/venv/lib/python2.7/site-packages/pip/download.py", line 278, in get_file_content
        raise InstallationError('Could not open requirements file: %s' % str(e))
    pip.exceptions.InstallationError: Could not open requirements file: [Errno 2] No such file or directory: 'requirements.txt'
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):

  File "<string>", line 17, in <module>

  File "/Users/theskumar/work/pr/myproject/venv/build/django-versatileimagefield/setup.py", line 22, in <module>

    for ir in parse_requirements('requirements.txt')

  File "/Users/theskumar/work/pr/myproject/venv/lib/python2.7/site-packages/pip/req.py", line 1546, in parse_requirements

    session=session,

  File "/Users/theskumar/work/pr/myproject/venv/lib/python2.7/site-packages/pip/download.py", line 278, in get_file_content

    raise InstallationError('Could not open requirements file: %s' % str(e))

pip.exceptions.InstallationError: Could not open requirements file: [Errno 2] No such file or directory: 'requirements.txt'

----------------------------------------

serializer ignores extra_kwargs

The VersatileImageFieldSerializer for django rest framework integration doesn't seem to acknowledge the extra_kwargs Meta field.

For example, this doesn't work:

class ExampleSerializer(serializers.ModelSerializer):
    image = VersatileImageFieldSerializer(
        sizes=[...]
    )

    class Meta:
        model = ExampleModel
        fields = ('image', ...)
        extra_kwargs = {
            'image': {'required': False}
        }

But this does:

class ExampleSerializer(serializers.ModelSerializer):
    image = VersatileImageFieldSerializer(
        required=False,
        sizes=[...]
    )

    class Meta:
        model = ExampleModel
        fields = ('image', ...)

VersatileImageFieldSerializer doesn't show placeholder's urls

Hey there!

utils.py:

if image_instance: # returns False while placeholder should be used

def build_versatileimagefield_url_set(image_instance, size_set, request=None):
    """
    Returns a dictionary of urls corresponding to size_set
    - `image_instance`: A VersatileImageFieldFile
    - `size_set`: An iterable of 2-tuples, both strings. Example:
        [
            ('large', 'url'),
            ('medium', 'crop__400x400'),
            ('small', 'thumbnail__100x100')
        ]
        The above would lead to the following response:
        {
            'large': 'http://some.url/image.jpg',
            'medium': 'http://some.url/__sized__/image-crop-400x400.jpg',
            'small': 'http://some.url/__sized__/image-thumbnail-100x100.jpg',
        }
    - `request`:
    """
    size_set = validate_versatileimagefield_sizekey_list(size_set)
    to_return = {}
    if image_instance: # returns False while placeholder should be used
        for key, image_key in size_set:
            img_url = get_url_from_image_key(image_instance, image_key)
            if request is not None:
                img_url = request.build_absolute_uri(img_url)
            to_return[key] = img_url
    return to_return

AttributeError: 'VersatileImageFieldFile' object has no attribute 'delete_all_created_images'

I'm following the method detailed in the docs to delete all image renditions when an object is deleted by calling instance.image.delete_all_created_images() in a post_delete hook.
However when instance.image.delete_all_created_images() is called it throws an AttributeError. Inspecting the available properties on instance.image object reveals that only the delete method is available.

Do I need a special configuration to allow versatile image objects to have the delete_all_created_images method? How can I delete all image renditions from an object?

Post delete hook:

@receiver(models.signals.post_delete, sender=CaseStudy)
def delete_case_study_images(sender, instance, **kwargs):
    """
    Deletes CaseStudy image renditions on post_delete.
    """
    instance.image.delete_all_created_images()
    instance.image.delete()

Stack trace:

ERROR: case_studies.test.test_models:CaseStudyTestCase.test_deleted_case_studies_remove_cropped_thumbnails
  vi +14  my-project/case_studies/test/test_models.py  # test_deleted_case_studies_remove_cropped_thumbnails
    self.case_study.delete()
  vi +862 env/lib/python2.7/site-packages/django/db/models/base.py  # delete
    return collector.delete()
  vi +316 env/lib/python2.7/site-packages/django/db/models/deletion.py  # delete
    sender=model, instance=obj, using=self.using
  vi +192 env/lib/python2.7/site-packages/django/dispatch/dispatcher.py  # send
    response = receiver(signal=self, sender=sender, **named)
  vi +66  my-project/case_studies/models.py  # delete_case_study_images
    instance.image.delete_all_created_images()
AttributeError: 'VersatileImageFieldFile' object has no attribute 'delete_all_created_images'

image.url does not return placeholder

This is quite unexpected. What is the intention behind this?
I would think that it would be intuitive that image.url would also return the placeholder since the e.g. image.crop.--x-- does as well.

Also maybe it might be useful to document this behavior more clearly.

How to remove ppoi widget

Using

zones_img = VersatileImageField(verbose_name=_('Plan for zones'), upload_to='zones_img', blank=True)

I find myself with an extra widget in my form's HTML:

<div class="versatileimagefield"><input accept="image/jpeg,image/png" class="file-chooser clearablefileinputwithimagepreview form-control" id="id_general-main-zones_img_0" name="general-main-zones_img_0" type="file"> <input accept="image/jpeg,image/png" class="ppoi-input hiddeninput form-control" id="id_general-main-zones_img_1" name="general-main-zones_img_1" type="hidden"> </div>

How to remove the second input file field?

blank=True has no effect via django-rest-framework

In my model, has a VersatileImageField(u"picture", blank=True, null=True).
In Django Admin, it can be empty.
But in django-rest-framework, when I don't upload this field, It prompt me this field is required.

VersatileImageField's field name does not include form prefix

Hello,

Currently in my project, I am using form prefix introduced in Django 1.9 to identify different forms on the same page.

The HTML code generated by the widget is correct and has the proper form prefix added to the input name. But VersatileImageField's field name does not contain the form prefix (see code snippet below); All other standard field types tested will return field name with form prefix. Without prefixed field name, it is not possible to customize the widget using template tag or ugly hack like renaming the name in the view function is needed.

# model
class Product(models.Model):
    name = models.CharField(max_length=128)
    product_image = VersatileImageField(upload_to='product', ppoi_field='profile_pic_ppoi')

# form
class ProductForm(forms.ModelForm):
    class Meta:
        model = Product
        fields = ['name', 'product_image']

    def __init__(self, *args, **kwargs):
        super(ProductForm, self).__init__(*args, **kwargs)

# view 
def product_details(request, pk):
    product = Product.get(id=pk)
    form = ProductForm(instance=product, prefix='my')
    ctx = {
        'form': form
    }
    return TemplateResponse(request, 'product.html', ctx)

# template 
{{ form.name.name }}
{{ form.product_image.name }}   

# output
    my-name
    product_image

Progressive JPEGs

Hi,

Great django app, do you can add a progressive JPEGs option for cached images?

Crop, thumbnail etc not working

I've followed the basic examples and installed all requirements but I can't get crop or thumbnail creation to work.

AttributeError: 'VersatileImageFieldFile' object has no attribute 'crop'

Edit:

Pillow==3.0.0
django-versatileimagefield==1.2.2

VersatileImageFieldSerializer displays absolute url

Hello,

When i use the standard ImageField in my serializers, the full url is displayed, everything works fine. But when i use the VersatileImageFieldSerializer by giving a liste of parameters for exemple :

*models.py
logo = VersatileImageField(upload_to=shop_logo_path, height_field='height', width_field='width', null=True, blank=True)

*serializers.py
logo = VersatileImageFieldSerializer(
    sizes=[
        ('full_size', 'url'),
        ('thumbnail', 'thumbnail__100x100'),
        ('medium_square_crop', 'crop__400x400'),
        ('small_square_crop', 'crop__50x50')
    ]
)

Only the absolute url is displayed

"logo": {
    "medium_square_crop": "/media/__sized__/shop/VS/1890/asfd/68fc96d2-b890-48b6-88f0-b76d01cb95ef-crop-c0-5__0-5-400x400.jpg",
    "small_square_crop": "/media/__sized__/shop/VS/1890/asfd/68fc96d2-b890-48b6-88f0-b76d01cb95ef-crop-c0-5__0-5-50x50.jpg",
    "full_size": "/media/shop/VS/1890/asfd/68fc96d2-b890-48b6-88f0-b76d01cb95ef",
    "thumbnail": "/media/__sized__/shop/VS/1890/asfd/68fc96d2-b890-48b6-88f0-b76d01cb95ef-thumbnail-100x100.jpg"
},

I took a look at your code in serializers.py the function to_representation and to_native received a value parameter, which is a VersatilImage instance, also display the absolute url

<VersatileImageFieldFile: shop/VS/1890/asfd/68fc96d2-b890-48b6-88f0-b76d01cb95ef>
ipdb> value.url
'/media/shop/VS/1890/asfd/68fc96d2-b890-48b6-88f0-b76d01cb95ef'

pip freeze shows:

Django==1.8.4
Pillow==3.0.0
django-versatileimagefield==1.0.5
djangorestframework==3.1.3

Thanks for your work and your help.

King Regards.

Joel

Recreate Thumbnails/Crop if source image is newer than result

I'm using versatileimagefield to manage user avatars in my project.
Upon update of any avatar I simply update the fileds value like so:

mediapath = 'path/to/avatars/username.jpg"
user.avatar = mediapath
user.save()

this works as expected.

In some other parts of the project I need to generate thumbnails/cropped versions of those avatars:

thumb = user.avatar.crop['200x200'].url

this initially creates a new cropped version and places it in __sized__/avatars/ as expected.
However, if the "source" image has been changed since the thumbnail was first created it is not updated and the user is still represented by his/her old avatar.

I suspect this happens with ever other sizer and filter aswell

Suggested Fix

  • check file creation time of source/original and resulting image
  • if resulting image is older than original recreate the resulting image

import_module blows up when it can't import something in INSTALLED_APPS

Hi there, not sure if this is a problem in django-versatileimagefield or django-rules, but I don't really understand what is happening, so I will start here ๐Ÿ‘

I have a 'rules.apps.AutodiscoverRulesConfig' (docs) line in my INSTALLED_APPS which is some django-rules specific configuration for discovering my rules. However, your implementation of autodiscover() will call import_module and blow up when it can't import the AutodiscoverRulesConfig.

Any ideas what the fix should be?

The error I am seeing is below.

Traceback (most recent call last):
  File "./manage.py", line 8, in <module>
    execute_from_command_line(sys.argv)
  File "/home/lwm/velodrome/.venv/lib/python3.4/site-packages/django/core/management/__init__.py", line 350, in execute_from_command_line
    utility.execute()
  File "/home/lwm/velodrome/.venv/lib/python3.4/site-packages/django/core/management/__init__.py", line 324, in execute
    django.setup()
  File "/home/lwm/velodrome/.venv/lib/python3.4/site-packages/django/__init__.py", line 18, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "/home/lwm/velodrome/.venv/lib/python3.4/site-packages/django/apps/registry.py", line 108, in populate
    app_config.import_models(all_models)
  File "/home/lwm/velodrome/.venv/lib/python3.4/site-packages/django/apps/config.py", line 202, in import_models
    self.models_module = import_module(models_module_name)
  File "/usr/lib/python3.4/importlib/__init__.py", line 109, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 2254, in _gcd_import
  File "<frozen importlib._bootstrap>", line 2237, in _find_and_load
  File "<frozen importlib._bootstrap>", line 2226, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 1200, in _load_unlocked
  File "<frozen importlib._bootstrap>", line 1129, in _exec
  File "<frozen importlib._bootstrap>", line 1471, in exec_module
  File "<frozen importlib._bootstrap>", line 321, in _call_with_frames_removed
  File "/home/lwm/velodrome/velodrome/lock8/models.py", line 80, in <module>
    from versatileimagefield.fields import VersatileImageField
  File "/home/lwm/velodrome/.venv/src/django-versatileimagefield/versatileimagefield/fields.py", line 13, in <module>
    from .files import VersatileImageFieldFile, VersatileImageFileDescriptor
  File "/home/lwm/velodrome/.venv/src/django-versatileimagefield/versatileimagefield/files.py", line 11, in <module>
    from .mixins import VersatileImageMixIn
  File "/home/lwm/velodrome/.venv/src/django-versatileimagefield/versatileimagefield/mixins.py", line 12, in <module>
    autodiscover()
  File "/home/lwm/velodrome/.venv/src/django-versatileimagefield/versatileimagefield/registry.py", line 196, in autodiscover
    mod = import_module(app)
  File "/usr/lib/python3.4/importlib/__init__.py", line 109, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
ImportError: No module named 'rules.apps.AutodiscoverRulesConfig'; 'rules.apps' is not a package

`jpeg_resize_quality` set, but no effect

My Settings:

VERSATILEIMAGEFIELD_SETTINGS = {
    'jpeg_resize_quality': 20,
}

When I using in template as:

{{goods.picture.thumbnail.600x600}}

The thumbnail generated in __sized__ dir and size is 17KB.

But when I delete this resized picture and change jpeg_resize_quality to 90,
The new thumbnail file is 17KB too,
It seems this settings has no any effect.

Is this a bug?

Admin PPOI click widget broken in Firefox

When I edit an object which uses the VersatileImageField plus the ppoi feature, the red square is not editable in Firefox. When I click on an object in the listView, the red square is first positioned in the center of the image. When I reload the editView, the square is positioned in the upper left corner.

I cleared the browser cache and checked the browsers console for errors.

With Chrome the widget works

EXIF Metadata

Hi there @respondcreate

The EXIF Metadata auto-rotate functionality is a nice touch.

Except, when Apple's buggy Swift jpeg rendering library creates unwanted behavior in the metadata, resulting in unfavorable rotations server-side. Is there any way to disable the auto-rotate functionality? Or alternatively, perform a manual rotate operation?

EDIT: I stand corrected. The photo's EXIF data is being written properly which I verified with http://regex.info/exif.cgi

So I supposed I'm looking for the reverse question. Is there a way to turn auto-rotate on. If it's on by default is there a reason it might not be functioning properly? The full size image with setting 'url' is being mirrored and rotated appropriately. However, the cropped photos/thumbnails are not.

Thanks.

Faris

ValidationError when saving: (0.5,0.5) is in invalid ppoi

I get this ValidationError when I try to use the code from the PPOIField tutorial.

The weird thing is I can upload an image, and it shows up in the widget as expected. Then I save again (with or without changing anything) and then it throws this error.

Note my admin uses django-suit, but I'd think it doesn't interfere. (I just tried versatileimagefield
late as experiment, I'll look into it next time)

ValidationError at /dashboard/content/image/2/
["(0.5,0.5) is in invalid ppoi. A valid ppoi must provide two coordinates, one for the x axis and one for the y, where both values are between 0 and 1. You may pass it as either a two-position tuple like this: (0.5,0.5) or as a string where the two values are separated by an 'x' like this: '0.5x0.5'."]

Stack:

Traceback:
File "/home/vagrant/.virtualenvs/my-project/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
  111.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/vagrant/.virtualenvs/my-project/lib/python3.4/site-packages/django/contrib/admin/options.py" in wrapper
  583.                 return self.admin_site.admin_view(view)(*args, **kwargs)
File "/home/vagrant/.virtualenvs/my-project/lib/python3.4/site-packages/django/utils/decorators.py" in _wrapped_view
  105.                     response = view_func(request, *args, **kwargs)
File "/home/vagrant/.virtualenvs/my-project/lib/python3.4/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
  52.         response = view_func(request, *args, **kwargs)
File "/home/vagrant/.virtualenvs/my-project/lib/python3.4/site-packages/django/contrib/admin/sites.py" in inner
  206.             return view(request, *args, **kwargs)
File "/home/vagrant/.virtualenvs/my-project/lib/python3.4/site-packages/django/contrib/admin/options.py" in change_view
  1456.         return self.changeform_view(request, object_id, form_url, extra_context)
File "/home/vagrant/.virtualenvs/my-project/lib/python3.4/site-packages/django/utils/decorators.py" in _wrapper
  29.             return bound_func(*args, **kwargs)
File "/home/vagrant/.virtualenvs/my-project/lib/python3.4/site-packages/django/utils/decorators.py" in _wrapped_view
  105.                     response = view_func(request, *args, **kwargs)
File "/home/vagrant/.virtualenvs/my-project/lib/python3.4/site-packages/django/utils/decorators.py" in bound_func
  25.                 return func.__get__(self, type(self))(*args2, **kwargs2)
File "/home/vagrant/.virtualenvs/my-project/lib/python3.4/site-packages/django/db/transaction.py" in inner
  394.                 return func(*args, **kwargs)
File "/home/vagrant/.virtualenvs/my-project/lib/python3.4/site-packages/django/contrib/admin/options.py" in changeform_view
  1396.             if form.is_valid():
File "/home/vagrant/.virtualenvs/my-project/lib/python3.4/site-packages/django/forms/forms.py" in is_valid
  162.         return self.is_bound and not bool(self.errors)
File "/home/vagrant/.virtualenvs/my-project/lib/python3.4/site-packages/django/forms/forms.py" in errors
  154.             self.full_clean()
File "/home/vagrant/.virtualenvs/my-project/lib/python3.4/site-packages/django/forms/forms.py" in full_clean
  355.         self._post_clean()
File "/home/vagrant/.virtualenvs/my-project/lib/python3.4/site-packages/django/forms/models.py" in _post_clean
  406.         self.instance = construct_instance(self, self.instance, opts.fields, opts.exclude)
File "/home/vagrant/.virtualenvs/my-project/lib/python3.4/site-packages/django/forms/models.py" in construct_instance
  60.             f.save_form_data(instance, cleaned_data[f.name])
File "/home/vagrant/.virtualenvs/my-project/lib/python3.4/site-packages/django/db/models/fields/__init__.py" in save_form_data
  804.         setattr(instance, self.name, data)
File "/home/vagrant/.virtualenvs/my-project/lib/python3.4/site-packages/django/db/models/fields/subclassing.py" in __set__
  37.         obj.__dict__[self.field.name] = self.field.to_python(value)
File "/home/vagrant/.virtualenvs/my-project/lib/python3.4/site-packages/versatileimagefield/fields.py" in to_python
  171.             value, return_converted_tuple=True
File "/home/vagrant/.virtualenvs/my-project/lib/python3.4/site-packages/versatileimagefield/validators.py" in validate_ppoi
  72.             code='invalid_ppoi'

PlaceHolderImage Image size 0

OnDiscPlaceholderImage seem to have a bug in it:

This line: self.image_data = ContentFile(file.read(), name=name) causes the file to be read.
The next line super(OnDiscPlaceholderImage, self).__init__(file, name) is setting self.image_data again using file.read(), however file.read() will now return '' thus self.image_data is always ''

I found this when I was writing a custom placeholder image class that reads from STATIC rather than MEDIA

Widget customisation

It would be cool to have some more control over the widgets and fields.

For example the 300x300 hardcoded thumbnail size is a bit much, and many of the widget templates are inlined in the python code.

I tried a bit of extending/overriding but it gets messy and various bits of functionality break down (thumbnail and PPOI functionality go MIA easily).

Maybe it would help to externalize the templates and have the admin thumbnail size configurable (per widget/form), also in some tight layouts we don't need the labels or current image url.

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.

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

Image preview disappearing on POST

Short explanation
When a form validation error occurs, VersatileImageField shows as if the field data truly is blank even when there was a previously uploaded photo.

So instead of seeing this...
image

...I see this...
image

When malfunction occurs

  • PPOI feature is enabled by using ppoi_field="photoppoi" in the models file.
  • AND a server-side validation error occurs in the form in an unrelated field.

When things work properly

  • Using VersatileImageField without setting ppoi_field
  • or using Django's built-in ImageField instead of VersatileImageField

Further details
With the typical code being used in views.py (see below), most of the time the user sees the form after it was created using PersonForm(instance=person). When the form is submitted, if everything is valid the user is immediately redirected to a clean form. But if there is a validation error, this redirect does not occur and the form is displayed after being created with PersonForm(request.POST, request.FILES, instance=person).

  person = Person.objects.get(pk=1)
  if request.method == 'POST':
    form = PersonForm(request.POST, request.FILES, instance=person)
    if form.is_valid():
      form.instance.save()
      return HttpResponseRedirect('/self/')
  else:
    form = PersonForm(instance=person)
  # Render the form
  return HttpResponse(template.render(Context(context)))

In this condition, bound_data is called against the field.

  • When PPOI is not used, the field is an ImageField, so this method is inherited from FileField django/forms/fields.py, line 611. When data is None (file uploaded previously, but not changed during this render of the form), the return value is initial (the file already uploaded).
    def bound_data(self, data, initial):
        if data in (None, FILE_INPUT_CONTRADICTION):
            return initial
        return data
  • When PPOI is in use, however, the field is a SizedImageCenterpointClickDjangoAdminField, based off of django's MultiValueField. But since bound_data was not implemented, it is ultimately inherited from the base Field class django/forms/fields.py, line 171. Here, for reasons unknown to me, django ignores initial and simply returns data. But in this situation, data is None, so VersatileImageField shows blank.
    def bound_data(self, data, initial):
        """
        Return the value that should be shown for this field on render of a
        bound form, given the submitted POST data for the field and the initial
        data, if any.

        For most fields, this will simply be data; FileFields need to handle it
        a bit differently.
        """
        return data

Possible fix
Since I can't profess to be a Django expert, I'm not sure if this is the best way to fix the problem. But it seems to work on my end:

In versatileimagefield/forms.py insert the following lines at line 49 (implement the bound_data method to the VersatileImagePPOIClickField class):

    def bound_data(self, data, initial):
        if (data[0] == None):
            return initial
        return data

'SizedImageInstance' object has no attribute 'width' / 'height'

I'm migrating from sorl-thumbnail to VersatileImageField and I like pretty much this lib.
By the way during some code migration I encountered many times the same exception:

'SizedImageInstance' object has no attribute 'width' / 'height'

That's really easy to fix, but I think that a SizedImageInstance obj could provide width/height properties.
What do you think about it?

Thanks for this great lib.

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

Server Error when no media exists for VersatileImageFieldSerializer

Hello, it appears that when an error is deleted on the operating system, the following error is returned when using VersatileImageFieldSerializer:

IOError: [Errno 2] No such file or directory:

Instead it may be better to return None or allow for a more graceful failure on a server rather than a server error.

I encountered this error via a database dump that had image instances already which have no files associated in my local environment since I'm not using an external image storage service like s3 locally.

Any help or thoughts would be appreciated

Throw IOError when file not found

Some time's I will dump server's database to my development machine to test.

But I won't download all pictures from my server.

Then all of picture will not exists, It prompt IOError.

How do I capture this Exception?

Document propogation of resized image width/height

I love this:

<img class="img-fluid" src="{{image.image.crop.720x300.url}}"/>

Is it possible to do this somehow:

<img class="img-fluid" src="{{image.image.crop.720x300.url}}" width="{{image.image.crop.720x300.width}}" height="{{image.image.crop.720x300.height}}"/>

Documentation on built-in sizers and filters could be expanded on a bit too... please!

No such file or directory on delete_all_created_images()

When I run delete_all_created_images() on a instance of a VersatileImageField with some sized thumbnails (no filtered and filtered+sized) I receive an error:

OSError at /admin/gallery/album/1/
[Errno 2] No such file or directory: '/my/upload/path/__filtered__'

Ideally I should be able to call delete_all_created_images() even if I don't use one or more of sized, filtered or filtered+sized images.

The workaround is of course to only call the delete_*_images()-method that reflects the images you use, but then you have to remember to add the other delete-methods if you start using one of the others types in the future.

Absolute urls in Django REST Framework serialzer

Hi,

I'm trying to find how to use absolute urls in the DRF serializer but I'm not sure it's possible today. Could you guide me on how I should implement this feature? I'm guessing it will become especially important when it will be possible to store on other storage services such as S3.

Admin 'PPOI click widget' fails intermittently

The admin widget intermittently fails to load correctly, displaying the red square in the top-right corner and not allowing the user to click anywhere on the image (to set an image's PPOI value).

Setting geometry for width/height only

Is there is a way to do something like:

example.image.crop['400x']

or

   example.image.crop['x400']

so resulting image would have exact/maximum width/height like in sorl-thumbnail?

Cropped images are not recreated if deleted during runtime

This issue is related to #25

Since images are not recreated upon update of the source image I tried to work around this issue by simply deleting the cropped images whenever the source image is updated.

However, versatileimagefield does not check if the cropped image still exists on the system and therefore returns invalid urls, resulting in 404 Errors for the users.

Only after a restart of the server the cropped images are created again.

Possible Fix
Recreate sizer/filter result file if not present on the filesystem

Compress images without applying any sizer or filter?

I would like to compress images to a target filesize or quality percentage and retain the original resolution. I don't know if this can be accomplished with a sizer because it requires non-specific dimensions.

In English, the goal of this functionality would be to answer the following: "Keep an original copy of all uploaded images, and serve a compressed version that has the same dimensions."

Additional optional functionality:

  • Passthrough images that are already compressed, under a certain filesize or filesize/pixels limit. I.e., "If an uploaded image is under 1mb, do not compress it" or "If an uploaded image is under 1 byte per pixel (1mb for a 1000x1000 image), do not compress it".
  • Separate treatment for images that have a large filesize but are detected to be high in entropy (indicated a high quality image that should not be compressed as much). I.e. "If an image is greater than 1mb, compress it a lot if there's low entropy (probably taken with a low quality phone camera). Compress it very little or not at all if there's a lot of entropy (every pixel is carrying detail)."

Is this something that DVIF would be interested in implementing?

DecompressionBombWarning

How do I solve this error?

DecompressionBombWarning: Image size (209255487 pixels) exceeds limit of 89478485 pixels, could be decompression bomb DOS attack.

Access to image field instance within sizer or filter class

Hi,

I need to add dynamic watermarks (eg: photographer name, copyright, url) into the cropped image. It's important to do it after image has been cropped because it should be scaled and uncut.
Is there a way to access image field instance from process_image method?

Thanks

Add an option/setting to catch exception when file to crop/thumbnail cannot be opened

Sometimes, your database and media files can get out of sync, for example if you load a DB backup on your development machine without downloading the media files corresponding to this backup.

In this situation, the database may refers to a media file that does not actually exist on disk. Then, trying to generate a thumbnail or cropping the image will raise a FileNotFoundError. Dummy code to generate the issue, assuming the image is not present on disk:

{{ blog_entry.featured_image.thumbnail.200x200 }}

This will generate a stack trace such as:

Traceback:

File "/root/.local/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
  174.                     response = self.process_exception_by_middleware(e, request)

File "/root/.local/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
  172.                     response = response.render()

File "/root/.local/lib/python3.4/site-packages/django/template/response.py" in render
  160.             self.content = self.rendered_content

File "/root/.local/lib/python3.4/site-packages/versatileimagefield/datastructures/sizedimage.py" in __getitem__
  120.                             height=height

File "/root/.local/lib/python3.4/site-packages/versatileimagefield/datastructures/sizedimage.py" in create_resized_image
  168.             path_to_image

File "/root/.local/lib/python3.4/site-packages/versatileimagefield/datastructures/base.py" in retrieve_image
  140.         image = self.storage.open(path_to_image, 'rb')

File "/root/.local/lib/python3.4/site-packages/django/core/files/storage.py" in open
  37.         return self._open(name, mode)

File "/root/.local/lib/python3.4/site-packages/django/core/files/storage.py" in _open
  201.         return File(open(self.path(name), mode))

Exception Type: FileNotFoundError at /url/
Exception Value: [Errno 2] No such file or directory: '/code/media/blog/2016/05/70-dummy-file-not-present-on-disk.png'

While this is a totally acceptable behaviour in production, where you don't want any missing file, on development / staging environment, this is quite painful, because any missing file can potentially make the whole template rendering step to crash.

Because of that, we cannot adopt versatileimagefield on our project, because it basically beak our development workflow: we update our local databases more often than media files, since we have gigabytes of media files, meaning that every page where we display a thumbnail can potentially crash.

To prevent this behaviour, I was thinking of adding an additional setting, such as VERSATILEIMAGEFIELD_SETTINGS['fail_silently_on_missing_file'], that would default to False, to preserve backward compatibility. Then, by wrapping the cropping/thumbnail process with a try / except FileNotFoundError, we could just skip the exception, logging it somewhere and forget about it.

I'm not sure if it's implementable though, and maybe there are reasons not do to this. Anyway, thank you for your time, and I hope we'll be able to find a workaround for this.

install fails with pip 6+

installing django versatile image field with pip 6+ raises the following error

Collecting django-versatileimagefield
  Using cached django-versatileimagefield-0.5.tar.gz
    Traceback (most recent call last):
      File "<string>", line 20, in <module>
      File "/var/folders/vc/7wgsmmhd2xl2v5djtg7m74n00000gn/T/pip-build-m_GYdH/django-versatileimagefield/setup.py", line 22, in <module>
        for ir in parse_requirements('requirements.txt')
      File "/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pip-6.0.3-py2.7.egg/pip/req/req_file.py", line 19, in parse_requirements
        "parse_requirements() missing 1 required keyword argument: "
    TypeError: parse_requirements() missing 1 required keyword argument: 'session'
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):

      File "<string>", line 20, in <module>

      File "/var/folders/vc/7wgsmmhd2xl2v5djtg7m74n00000gn/T/pip-build-m_GYdH/django-versatileimagefield/setup.py", line 22, in <module>

        for ir in parse_requirements('requirements.txt')

      File "/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pip-6.0.3-py2.7.egg/pip/req/req_file.py", line 19, in parse_requirements

        "parse_requirements() missing 1 required keyword argument: "

    TypeError: parse_requirements() missing 1 required keyword argument: 'session'

    ----------------------------------------
    Command "python setup.py egg_info" failed with error code 1 in /var/folders/vc/7wgsmmhd2xl2v5djtg7m74n00000gn/T/pip-build-m_GYdH/django-versatileimagefieldd keyword argument: 'session'

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.

Attribute Error

I attempted to incorporate a basic versatile photo field directly from the tutorial into my pre-existing Django Rest API (3.4.3) with Django 1.10, and unfortunately I am getting the error:

'VersatileImageFieldFile' object has no attribute '__getitem__'

upon access of the model's URL. Any idea why this is happening?

I am running my API to store images in an S3 bucket so it is my assumption that this has something to do with it. Does your framework support AWS integration?

NOTE: All is well when a standard image field is used instead.

Thanks!

Provide a non-clearable image field

Making the field clearable makes little sense for required fields and results in confusing UI. Currently making the field non-clearable requires subclassing the model field, the form field and the widget.

Force JPEG (or other web compatible format) on upload?

Is there a way to force all images to be converted to JPG if their fileformat is not one of a given set of formats? Effectively, I want to be able to generate thumbnails that a browser can display even if the end users uploads a TIFF or other format which browsers don't usually display.

I look into writing my own custom sizer, which would allow me to override the format key in the save_kwargs - but it doesn't allow me to override the image extension.

If this is possible, then the pattern should be added to the docs, if it's not possible then is it something that will be considered for future versions?

if field is null raises IsADirectoryError

this line:
{{ web_funcionarios.cargo.en_funcion_activa.funcionario.foto.thumbnail.125x125 }}

Raises IsADirectoryError if web_funcionarios.cargo.en_funcion_activa.funcionario.foto is None.

in the shell:

>>> WebFuncionarios.objects.all()[0].cargo.en_funcion_activa.funcionario.foto
<VersatileImageFieldFile: None>
>>>

runserver log:

[28/Jul/2016 14:39:25] "GET /funcionarios/organigrama HTTP/1.1" 500 266295
Internal Server Error: /funcionarios/organigrama
Traceback (most recent call last):
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/core/handlers/base.py", line 149, in get_response
    response = self.process_exception_by_middleware(e, request)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/core/handlers/base.py", line 147, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/utils/decorators.py", line 149, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/home/ignacio/proyectos/Qhapax/website/views_funcionarios.py", line 33, in home
    return render(request, url, context)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/shortcuts.py", line 67, in render
    template_name, context, request=request, using=using)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/template/loader.py", line 97, in render_to_string
    return template.render(context, request)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/template/backends/django.py", line 95, in render
    return self.template.render(context)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/template/base.py", line 206, in render
    return self._render(context)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/template/base.py", line 197, in _render
    return self.nodelist.render(context)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/template/base.py", line 992, in render
    bit = node.render_annotated(context)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/template/base.py", line 959, in render_annotated
    return self.render(context)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/template/loader_tags.py", line 173, in render
    return compiled_parent._render(context)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/template/base.py", line 197, in _render
    return self.nodelist.render(context)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/template/base.py", line 992, in render
    bit = node.render_annotated(context)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/template/base.py", line 959, in render_annotated
    return self.render(context)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/template/loader_tags.py", line 69, in render
    result = block.nodelist.render(context)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/template/base.py", line 992, in render
    bit = node.render_annotated(context)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/template/base.py", line 959, in render_annotated
    return self.render(context)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/template/defaulttags.py", line 220, in render
    nodelist.append(node.render_annotated(context))
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/template/base.py", line 959, in render_annotated
    return self.render(context)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/template/defaulttags.py", line 326, in render
    return nodelist.render(context)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/template/base.py", line 992, in render
    bit = node.render_annotated(context)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/template/base.py", line 959, in render_annotated
    return self.render(context)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/template/defaulttags.py", line 326, in render
    return nodelist.render(context)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/template/base.py", line 992, in render
    bit = node.render_annotated(context)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/template/base.py", line 959, in render_annotated
    return self.render(context)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/template/base.py", line 1043, in render
    output = self.filter_expression.resolve(context)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/template/base.py", line 709, in resolve
    obj = self.var.resolve(context)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/template/base.py", line 850, in resolve
    value = self._resolve_lookup(context)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/template/base.py", line 883, in _resolve_lookup
    current = current[bit]
  File "/home/ignacio/py3/lib/python3.5/site-packages/versatileimagefield/datastructures/sizedimage.py", line 120, in __getitem__
    height=height
  File "/home/ignacio/py3/lib/python3.5/site-packages/versatileimagefield/datastructures/sizedimage.py", line 168, in create_resized_image
    path_to_image
  File "/home/ignacio/py3/lib/python3.5/site-packages/versatileimagefield/datastructures/base.py", line 140, in retrieve_image
    image = self.storage.open(path_to_image, 'rb')
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/core/files/storage.py", line 37, in open
    return self._open(name, mode)
  File "/home/ignacio/py3/lib/python3.5/site-packages/django/core/files/storage.py", line 201, in _open
    return File(open(self.path(name), mode))
IsADirectoryError: [Errno 21] Is a directory: '/home/ignacio/proyectos/Qhapax/media'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.