Automated image processing for Django. Currently v4.0

Related tags

Djangodjango-imagekit
Overview

Build Status

ImageKit is a Django app for processing images. Need a thumbnail? A black-and-white version of a user-uploaded image? ImageKit will make them for you. If you need to programatically generate one image from another, you need ImageKit.

ImageKit comes with a bunch of image processors for common tasks like resizing and cropping, but you can also create your own. For an idea of what's possible, check out the Instakit project.

For the complete documentation on the latest stable version of ImageKit, see ImageKit on RTD.

Installation

  1. Install PIL or Pillow. (If you're using an ImageField in Django, you should have already done this.)
  2. pip install django-imagekit
  3. Add 'imagekit' to your INSTALLED_APPS list in your project's settings.py

Note

If you've never seen Pillow before, it considers itself a more-frequently updated "friendly" fork of PIL that's compatible with setuptools. As such, it shares the same namespace as PIL does and is a drop-in replacement.

Usage Overview

Specs

You have one image and you want to do something to it to create another image. But how do you tell ImageKit what to do? By defining an image spec.

An image spec is a type of image generator that generates a new image from a source image.

Defining Specs In Models

The easiest way to use define an image spec is by using an ImageSpecField on your model class:

from django.db import models
from imagekit.models import ImageSpecField
from imagekit.processors import ResizeToFill

class Profile(models.Model):
    avatar = models.ImageField(upload_to='avatars')
    avatar_thumbnail = ImageSpecField(source='avatar',
                                      processors=[ResizeToFill(100, 50)],
                                      format='JPEG',
                                      options={'quality': 60})

profile = Profile.objects.all()[0]
print(profile.avatar_thumbnail.url)    # > /media/CACHE/images/982d5af84cddddfd0fbf70892b4431e4.jpg
print(profile.avatar_thumbnail.width)  # > 100

As you can probably tell, ImageSpecFields work a lot like Django's ImageFields. The difference is that they're automatically generated by ImageKit based on the instructions you give. In the example above, the avatar thumbnail is a resized version of the avatar image, saved as a JPEG with a quality of 60.

Sometimes, however, you don't need to keep the original image (the avatar in the above example); when the user uploads an image, you just want to process it and save the result. In those cases, you can use the ProcessedImageField class:

from django.db import models
from imagekit.models import ProcessedImageField
from imagekit.processors import ResizeToFill

class Profile(models.Model):
    avatar_thumbnail = ProcessedImageField(upload_to='avatars',
                                           processors=[ResizeToFill(100, 50)],
                                           format='JPEG',
                                           options={'quality': 60})

profile = Profile.objects.all()[0]
print(profile.avatar_thumbnail.url)    # > /media/avatars/MY-avatar.jpg
print(profile.avatar_thumbnail.width)  # > 100

This is pretty similar to our previous example. We don't need to specify a "source" any more since we're not processing another image field, but we do need to pass an "upload_to" argument. This behaves exactly as it does for Django ImageFields.

Note

You might be wondering why we didn't need an "upload_to" argument for our ImageSpecField. The reason is that ProcessedImageFields really are just like ImageFields—they save the file path in the database and you need to run syncdb (or create a migration) when you add one to your model.

ImageSpecFields, on the other hand, are virtual—they add no fields to your database and don't require a database. This is handy for a lot of reasons, but it means that the path to the image file needs to be programmatically constructed based on the source image and the spec.

Defining Specs Outside of Models

Defining specs as models fields is one very convenient way to process images, but it isn't the only way. Sometimes you can't (or don't want to) add fields to your models, and that's okay. You can define image spec classes and use them directly. This can be especially useful for doing image processing in views— particularly when the processing being done depends on user input.

from imagekit import ImageSpec
from imagekit.processors import ResizeToFill

class Thumbnail(ImageSpec):
    processors = [ResizeToFill(100, 50)]
    format = 'JPEG'
    options = {'quality': 60}

It's probably not surprising that this class is capable of processing an image in the exact same way as our ImageSpecField above. However, unlike with the image spec model field, this class doesn't define what source the spec is acting on, or what should be done with the result; that's up to you:

source_file = open('/path/to/myimage.jpg', 'rb')
image_generator = Thumbnail(source=source_file)
result = image_generator.generate()

Note

You don't have to use open! You can use whatever File-like object you want—including a model's ImageField.

The result of calling generate() on an image spec is a file-like object containing our resized image, with which you can do whatever you want. For example, if you wanted to save it to disk:

dest = open('/path/to/dest.jpg', 'wb')
dest.write(result.read())
dest.close()

Using Specs In Templates

If you have a model with an ImageSpecField or ProcessedImageField, you can easily use those processed image just as you would a normal image field:

<img src="{{ profile.avatar_thumbnail.url }}" />

(This is assuming you have a view that's setting a context variable named "profile" to an instance of our Profile model.)

But you can also generate processed image files directly in your template—from any image—without adding anything to your model. In order to do this, you'll first have to define an image generator class (remember, specs are a type of generator) in your app somewhere, just as we did in the last section. You'll also need a way of referring to the generator in your template, so you'll need to register it.

from imagekit import ImageSpec, register
from imagekit.processors import ResizeToFill

class Thumbnail(ImageSpec):
    processors = [ResizeToFill(100, 50)]
    format = 'JPEG'
    options = {'quality': 60}

register.generator('myapp:thumbnail', Thumbnail)

Note

You can register your generator with any id you want, but choose wisely! If you pick something too generic, you could have a conflict with another third-party app you're using. For this reason, it's a good idea to prefix your generator ids with the name of your app. Also, ImageKit recognizes colons as separators when doing pattern matching (e.g. in the generateimages management command), so it's a good idea to use those too!

Warning

This code can go in any file you want—but you need to make sure it's loaded! In order to keep things simple, ImageKit will automatically try to load an module named "imagegenerators" in each of your installed apps. So why don't you just save yourself the headache and put your image specs in there?

Now that we've created an image generator class and registered it with ImageKit, we can use it in our templates!

generateimage

The most generic template tag that ImageKit gives you is called "generateimage". It requires at least one argument: the id of a registered image generator. Additional keyword-style arguments are passed to the registered generator class. As we saw above, image spec constructors expect a source keyword argument, so that's what we need to pass to use our thumbnail spec:

{% load imagekit %}

{% generateimage 'myapp:thumbnail' source=source_file %}

This will output the following HTML:

<img src="/media/CACHE/images/982d5af84cddddfd0fbf70892b4431e4.jpg" width="100" height="50" />

You can also add additional HTML attributes; just separate them from your keyword args using two dashes:

{% load imagekit %}

{% generateimage 'myapp:thumbnail' source=source_file -- alt="A picture of Me" id="mypicture" %}

Not generating HTML image tags? No problem. The tag also functions as an assignment tag, providing access to the underlying file object:

{% load imagekit %}

{% generateimage 'myapp:thumbnail' source=source_file as th %}
<a href="{{ th.url }}">Click to download a cool {{ th.width }} x {{ th.height }} image!</a>
thumbnail

Because it's such a common use case, ImageKit also provides a "thumbnail" template tag:

{% load imagekit %}

{% thumbnail '100x50' source_file %}

Like the generateimage tag, the thumbnail tag outputs an <img> tag:

<img src="/media/CACHE/images/982d5af84cddddfd0fbf70892b4431e4.jpg" width="100" height="50" />

Comparing this syntax to the generateimage tag above, you'll notice a few differences.

First, we didn't have to specify an image generator id; unless we tell it otherwise, thumbnail tag uses the generator registered with the id "imagekit:thumbnail". It's important to note that this tag is *not* using the Thumbnail spec class we defined earlier; it's using the generator registered with the id "imagekit:thumbnail" which, by default, is imagekit.generatorlibrary.Thumbnail.

Second, we're passing two positional arguments (the dimensions and the source image) as opposed to the keyword arguments we used with the generateimage tag.

Like with the generateimage tag, you can also specify additional HTML attributes for the thumbnail tag, or use it as an assignment tag:

{% load imagekit %}

{% thumbnail '100x50' source_file -- alt="A picture of Me" id="mypicture" %}
{% thumbnail '100x50' source_file as th %}

Using Specs in Forms

In addition to the model field above, there's also a form field version of the ProcessedImageField class. The functionality is basically the same (it processes an image once and saves the result), but it's used in a form class:

from django import forms
from imagekit.forms import ProcessedImageField
from imagekit.processors import ResizeToFill

class ProfileForm(forms.Form):
    avatar_thumbnail = ProcessedImageField(spec_id='myapp:profile:avatar_thumbnail',
                                           processors=[ResizeToFill(100, 50)],
                                           format='JPEG',
                                           options={'quality': 60})

The benefit of using imagekit.forms.ProcessedImageField (as opposed to imagekit.models.ProcessedImageField above) is that it keeps the logic for creating the image outside of your model (in which you would use a normal Django ImageField). You can even create multiple forms, each with their own ProcessedImageField, that all store their results in the same image field.

Processors

So far, we've only seen one processor: imagekit.processors.ResizeToFill. But ImageKit is capable of far more than just resizing images, and that power comes from its processors.

Processors take a PIL image object, do something to it, and return a new one. A spec can make use of as many processors as you'd like, which will all be run in order.

from imagekit import ImageSpec
from imagekit.processors import TrimBorderColor, Adjust

class MySpec(ImageSpec):
    processors = [
        TrimBorderColor(),
        Adjust(contrast=1.2, sharpness=1.1),
    ]
    format = 'JPEG'
    options = {'quality': 60}

The imagekit.processors module contains processors for many common image manipulations, like resizing, rotating, and color adjustments. However, if they aren't up to the task, you can create your own. All you have to do is define a class that implements a process() method:

class Watermark(object):
    def process(self, image):
        # Code for adding the watermark goes here.
        return image

That's all there is to it! To use your fancy new custom processor, just include it in your spec's processors list:

from imagekit import ImageSpec
from imagekit.processors import TrimBorderColor, Adjust
from myapp.processors import Watermark

class MySpec(ImageSpec):
    processors = [
        TrimBorderColor(),
        Adjust(contrast=1.2, sharpness=1.1),
        Watermark(),
    ]
    format = 'JPEG'
    options = {'quality': 60}

Note that when you import a processor from imagekit.processors, imagekit in turn imports the processor from PILKit. So if you are looking for available processors, look at PILKit.

Admin

ImageKit also contains a class named imagekit.admin.AdminThumbnail for displaying specs (or even regular ImageFields) in the Django admin change list. AdminThumbnail is used as a property on Django admin classes:

from django.contrib import admin
from imagekit.admin import AdminThumbnail
from .models import Photo

class PhotoAdmin(admin.ModelAdmin):
    list_display = ('__str__', 'admin_thumbnail')
    admin_thumbnail = AdminThumbnail(image_field='thumbnail')

admin.site.register(Photo, PhotoAdmin)

To use specs defined outside of models:

from django.contrib import admin
from imagekit.admin import AdminThumbnail
from imagekit import ImageSpec
from imagekit.processors import ResizeToFill
from imagekit.cachefiles import ImageCacheFile

from .models import Photo

class AdminThumbnailSpec(ImageSpec):
    processors = [ResizeToFill(100, 30)]
    format = 'JPEG'
    options = {'quality': 60 }

def cached_admin_thumb(instance):
    # `image` is the name of the image field on the model
    cached = ImageCacheFile(AdminThumbnailSpec(instance.image))
    # only generates the first time, subsequent calls use cache
    cached.generate()
    return cached

class PhotoAdmin(admin.ModelAdmin):
    list_display = ('__str__', 'admin_thumbnail')
    admin_thumbnail = AdminThumbnail(image_field=cached_admin_thumb)

admin.site.register(Photo, PhotoAdmin)

AdminThumbnail can even use a custom template. For more information, see imagekit.admin.AdminThumbnail.

Management Commands

ImageKit has one management command—generateimages—which will generate cache files for all of your registered image generators. You can also pass it a list of generator ids in order to generate images selectively.

Community

Please use the GitHub issue tracker to report bugs with django-imagekit. A mailing list also exists to discuss the project and ask questions, as well as the official #imagekit channel on Freenode.

Contributing

We love contributions! And you don't have to be an expert with the library—or even Django—to contribute either: ImageKit's processors are standalone classes that are completely separate from the more intimidating internals of Django's ORM. If you've written a processor that you think might be useful to other people, open a pull request so we can take a look!

You can also check out our list of open, contributor-friendly issues for ideas.

Check out our contributing guidelines for more information about pitching in with ImageKit.

Comments
  • 'ImageSpecFieldFile' object has no attribute 'field'

    'ImageSpecFieldFile' object has no attribute 'field'

    The latest version in the development branch fails to generate images, instead it throws the following error:

    'ImageSpecFieldFile' object has no attribute 'field'
    
    bug 
    opened by tijs 50
  • New API

    New API

    Here are the API changes we talked about! There's a lot different, but I think we provided some pretty good documentation (sphinx makefile is included) so I won't restate it all here. As a broad overview, though, the main points are:

    1. Field-centric design. This is probably the biggest shift. You define specs as properties on a Django model, instead of in their own module. preprocessor_spec has received a similar treatment and is now ProcessedImageField. One upside of this is that you no longer need to extend a special ImageModel class.
    2. Processor instances are used instead of classes. This allows you to pass options to the constructor instead of defining a subclass.
    3. Simplified Processor interface. The old Processor interface was tied to the ORM-parts of IK (and therefore Django's ORM itself). The new one is much simplified, and allows processors to be used completely separately from the ORM layer (in fact, completely separate of Django itself).

    This is the result of a lot of hard work and we're very excited about it. We spent a lot of time talking about what a "spec" was and wasn't, and paid special attention to the division between processors and specs. I think the result is something a little more idiomatic and (more importantly, I guess) easier to use.

    Looking very forward to hearing your thoughts!

    (In case anybody doesn't want to bother generating the docs, HZ will host them (temporarily) at ikdocs.hzdesign.com for you to check out while we discuss.)

    opened by matthewwithanm 27
  • `from imagekit.processors import ResizeToFill` not working

    `from imagekit.processors import ResizeToFill` not working

    Code from imagekit.processors import ResizeToFill, as stated in the docs, is not working.

    http://django-imagekit.readthedocs.org/en/latest/

    Looking at processors.py I read this:

    """ Looking for processors? They have moved to PILKit. See imagekit.importers for details.

    """

    Looks like this is not covered in the docs.

    opened by danielniccoli 25
  • image in feeds.py

    image in feeds.py

    I am getting an error when an thumbnail doesn't exist in the cache for an image used in a rss feed. handler.addQuickElement(u"url", show.img_itunes_sm.url) from https://github.com/rizumu/django-podcasting/blob/master/podcasting/feeds.py

    The error is triggerd in utils.py when calling img.save():

        ipdb> img
        <PIL.Image.Image image mode=RGB size=1000x1000 at 0x3A64290>
        ipdb> img.save(tmp, format, **kwargs)
        Suspension not allowed here
        *** IOError: encoder error -2 when writing image file
    

    and the traceback

     Environment:
    
    Request Method: GET
    Request URL: http://snowprayers.net/feeds/podcasts/snowprayers/itunes/mp3/rss/
    
    
    Traceback:
    File "/home/deploy/.virtualenvs/snowprayers/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
      111.                         response = callback(request, *callback_args, **callback_kwargs)
    File "/home/deploy/.virtualenvs/snowprayers/lib/python2.7/site-packages/newrelic-0.5.58.122/newrelic/hooks/framework_django.py" in __call__
      327.                     return self.__wrapped(*args, **kwargs)
    File "/home/deploy/.virtualenvs/snowprayers/lib/python2.7/site-packages/django/contrib/syndication/views.py" in __call__
      39.         feedgen.write(response, 'utf-8')
    File "/home/deploy/.virtualenvs/snowprayers/lib/python2.7/site-packages/django/utils/feedgenerator.py" in write
      214.         self.add_root_elements(handler)
    File "/home/deploy/.virtualenvs/snowprayers/lib/python2.7/site-packages/podcasting/feeds.py" in add_root_elements
      39.         handler.addQuickElement(u"itunes:image", attrs={"href": show.img_itunes_lg.url})
    File "/home/deploy/.virtualenvs/snowprayers/lib/python2.7/site-packages/imagekit/models.py" in url
      159.         self._create(True)
    File "/home/deploy/.virtualenvs/snowprayers/lib/python2.7/site-packages/imagekit/models.py" in _create
      184.             img, content = self._process_content(self.name, fp)
    File "/home/deploy/.virtualenvs/snowprayers/lib/python2.7/site-packages/imagekit/models.py" in _process_content
      135.                                   optimize=True)
    File "/home/deploy/.virtualenvs/snowprayers/lib/python2.7/site-packages/imagekit/utils.py" in img_to_fobj
      18.     img.save(tmp, format, **kwargs)
    File "/home/deploy/.virtualenvs/snowprayers/lib/python2.7/site-packages/PIL/Image.py" in save
      1439.             save_handler(self, fp, filename)
    File "/home/deploy/.virtualenvs/snowprayers/lib/python2.7/site-packages/PIL/JpegImagePlugin.py" in _save
      471.     ImageFile._save(im, fp, [("jpeg", (0,0)+im.size, 0, rawmode)])
    File "/home/deploy/.virtualenvs/snowprayers/lib/python2.7/site-packages/PIL/ImageFile.py" in _save
      501.                 raise IOError("encoder error %d when writing image file" % s)
    
    Exception Type: IOError at /feeds/podcasts/snowprayers/itunes/mp3/rss/
    Exception Value: encoder error -2 when writing image file
    

    I'll attempt to figure it out over the weekend.

    opened by rizumu 25
  • thumbnail processing

    thumbnail processing

    Right now there are some implementations for Crop and Fit, but there is no implementation of generating a Thumbnail which is quite widely used.

    thumbnail

    http://www.pythonware.com/library/pil/handbook/image.htm

    Modifies the image to contain a thumbnail version of itself, no larger than the given size. This method calculates an appropriate thumbnail size to preserve the aspect of the image, calls the draft method to configure the file reader (where applicable), and finally resizes the image.

    Right now I'm using the crop method for this but I think it would be worth implementing? So if this is something that we should maybe have then please let me know. I'll fork and write a patch for this. If I'm mistaken and this feature is not needed or somehow implemented already then let me know.

    opened by madisvain 23
  • Error when trying to access width/height after url in templates

    Error when trying to access width/height after url in templates

    Error (see traceback below) occurs if you generate image with assignment tag and then access width or height after url. If you use width/height before url - everything goes fine. Also error disappears if you try to access already generated images.

    All the related settings are the default ones.

    Examples:

    from django.template import Template, Context
    tpl = "{% load imagekit %}{% generateimage 'spec_name' source=obj.photo as im %} {{ im.url }} {{ im.width }}"
    Template(tpl).render(Context({'obj': obj}))  # error
    # but no error for this:
    tpl = "... {{ im.width }} {{ im.url }}"
    # and also no error if thumb was already generated before render call
    

    It's quite strange and I'm not sure if that problem existed before because even in docs there's an example that is doing exactly the same things.

    Traceback:

    .../lib/python3.4/site-packages/django/core/files/images.py in _get_width(self)
         16     """
         17     def _get_width(self):
    ---> 18         return self._get_image_dimensions()[0]
         19     width = property(_get_width)
         20
    
    .../lib/python3.4/site-packages/django/core/files/images.py in _get_image_dimensions(self)
         26         if not hasattr(self, '_dimensions_cache'):
         27             close = self.closed
    ---> 28             self.open()
         29             self._dimensions_cache = get_image_dimensions(self, close=close)
         30         return self._dimensions_cache
    
    .../lib/python3.4/site-packages/imagekit/files.py in open(self, mode)
         57     def open(self, mode='rb'):
         58         self._require_file()
    ---> 59         self.file.open(mode)
         60
         61     def _get_closed(self):
    
    .../lib/python3.4/site-packages/django/core/files/base.py in open(self, mode)
        139             self.file = open(self.name, mode or self.mode)
        140         else:
    --> 141             raise ValueError("The file cannot be reopened.")
        142
        143     def close(self):
    

    PS. Confirmed for ImageKit 3.3 / Django 1.8-1.9 / Python 3.4.3

    bug 
    opened by a1tus 19
  • Add Python 3 suport

    Add Python 3 suport

    Add experimental Python 3 support. All python 2 test are passing, but tests must be refactored to run with newer nose version to be able to run with Python 3.

    opened by vstoykov 19
  • Cache_to is gone?

    Cache_to is gone?

    I'm not sure what's wrong. I upgraded to 3 and now my processed images or ImageSpecFields aren't showing up. I get UnsupportedOperation in Templates when I call {{ photo.medium.url }}. What do I do? What am I doing wrong?

    class ProfilePhotos(models.Model):
        user = models.ForeignKey(settings.AUTH_USER_MODEL)
        original = models.ImageField(upload_to=uuid_filename)
        large = ImageSpecField(
            processors=[Adjust(contrast=1.2, sharpness=1.1), ResizeToFit(870),ResizeToFill(870,870)],
            source = 'original',
            format = 'JPEG',
            options = {'quality': 90}
            #cache_to = '%slarge/' % settings.CACHE_TO
        )
    
    opened by hawksalon 19
  • Cache State Backends

    Cache State Backends

    Alright, here's my first crack at what @cyberdelia, @bryanveloso, and I were talking about in #88. Essentially, it's my solution to #74, #75, #81, and #88. In summary, ImageSpecs are no longer directly responsible for creating and deleting cached images. Instead they delegate the responsibility to "cache state backends."

    Cache state backends must implement two methods: invalidate() and validate(). The default backend maintains the current behavior: invalidating an image deletes it, and validating it creates the file (if it doesn't already exist). This behavior is very safe (which is why I think it makes a good default) but, as @mkai noted in #81, it can be prohibitively slow for certain file storage backends. This new setup allows him to define a much more optimistic backend that, for example, could immediately regenerate cache images on invalidation and define validation as a no-op. Since images are generally infrequently invalidated and frequently validated, this system would probably work out much better for him.

    Similarly, @davelowe could use a custom cache state backend to queue the creation of images via celery instead of having the processing of the image hold up his page loads.

    API Changes

    I ended up removing the pre_cache argument from the ImageSpec constructor. The main reason for this is that cache state backends provide a much more powerful mechanism for controlling this behavior. @bryanveloso's :+1: pushed me over the edge. I put in an exception to warn anybody who migrates.

    Since the decision about which cache state backend to use will likely be tightly coupled to your choice of storage, I wanted to make it very similar to use. Therefore, there are two ways to set a cache state backend:

    1. Pass an instance to the ImageSpec constructor (like the storage kwarg)
    2. Set IMAGEKIT_DEFAULT_CACHE_STATE_BACKEND in settings.py (like DEFAULT_FILE_STORAGE)

    In place of ikflush, we now have two shiny new management commands: ikcacheinvalidate and ikcachevalidate. (The old ikflush was dependent on pre_cache and that wasn't going to cut it anymore.) They work pretty much exactly how you'd expect. ikcachevalidate also accepts a --force flag which makes it behave like ikflush did when pre_cache was true; using this flag will cause each file to be invalidated and then immediately validated. (This is pretty much the same as running ikcacheinvalidate and then ikcachevalidate, except that would invalidate all files before validating any of them.)

    Finally, IK metadata ("_ik") is now bound to each model instance. I doubt anybody who's not hacking around in the guts of IK will even notice this change, but it makes acquiring a list of bound filefields a little prettier.

    So

    This is another nontrivial change, so I figured I'd submit a pull request for us to discus. So let's hear your thoughts! And, if you have some free time after that, here's some other stuff to do:

    1. Test it out (I haven't really tested much at all)
    2. Write some cache state backends! It would be nice if we could bundle a few with IK. The optimistic one I mentioned earlier might be a candidate.
    3. Docs, please!
    opened by matthewwithanm 18
  • Broken Celery

    Broken Celery

    When I try to fire up ./manage.py celeryd after integrating the latest imagekit into my models, I get this error:

    AttributeError: 'ImageSpecFile' object has no attribute 'source_file'

    https://gist.github.com/1352084

    Am I doing something wrong (hopefully) or is celery incompatible with imagekit?

    Thanks, Dave

    opened by davelowe 18
  • Relatively large files cause an issue with some of the processors

    Relatively large files cause an issue with some of the processors

    I ran ikflush and got a ton of 'Suspension not allowed here' messages. I was able to fix it by adding this line to the top of utils.py:

    ImageFile.MAXBLOCK = 1024 * 1024
    
    opened by pwfff 17
  • Accept `cachefile_storage` as callable

    Accept `cachefile_storage` as callable

    if not storage:
        storage = getattr(generator, 'cachefile_storage', None)
    if storage and callable(storage):
        storage = storage()
    else:
        storage = get_singleton(settings.IMAGEKIT_DEFAULT_FILE_STORAGE, 'file storage backend')
    
    opened by noors312 0
  • WEBP GIF's not working

    WEBP GIF's not working

    I am trying to upload a .gif image and process it to WEBP format and quality 90%. But it does not work, it only saves the first frame of the gif.

    I have been doing some research, and Pillow must receive the following arguments: duration and save_all image.save(im_io, 'webp', duration=image.info["duration"], save_all=True)

    But I don't know how can I send this parameters to imagekit model or if it is even possible.

    I have tried solving it using a processor, but as it process before the last save, and the last save is the problem... nothing seems to work.

    Thanks!

    opened by SantiMNV 0
  • docs: Fix a few typos

    docs: Fix a few typos

    There are small typos in:

    • docs/_themes/README.rst
    • docs/caching.rst
    • imagekit/files.py
    • imagekit/forms/fields.py
    • imagekit/specs/sourcegroups.py
    • tests/test_optimistic_strategy.py

    Fixes:

    • Should read underlying rather than underlaying.
    • Should read truthiness rather than thruthiness.
    • Should read separate rather than seprate.
    • Should read response rather than responce.
    • Should read represents rather than repesents.
    • Should read perform rather than peform.
    • Should read directly rather than dirrectly.
    • Should read derivative rather than drivative.

    Semi-automated pull request generated by https://github.com/timgates42/meticulous/blob/master/docs/NOTE.md

    opened by timgates42 0
  • Fix equality checking of paths by normalizing them

    Fix equality checking of paths by normalizing them

    The main reason for this PR is the final part of the FileSystemStorage._save() method in the Django library that leads to generating unnormalized paths:

    ...
    
    # Store filenames with forward slashes, even on Windows.
    return str(name).replace('\\', '/')
    

    So, we should care for the normalized paths generated by namer (using os.path.normpath()) against the unnormalized paths generated by Django Storage. Hence, this leads to a fault when the OS doesn't use forward slashes for the path formatting, like Windows.

    opened by armanexplorer 1
Releases(4.1.0)
  • 4.1.0(Dec 17, 2021)

    This is feature release. Add support for new Python and Django versions.

    • Supported Python versions are: 2.7, 3.6, 3.7, 3.8, 3.9, 3.10
    • Supported Django versions are: 1.8, 1.11, 2.2, 3.1, 3.2

    Upgrading since 4.0

    Nothing special except to ensure that you are using supported Python and Django version

    Changes since 4.0.2

    Full changelog 4.0.2...4.1.0

    Highlights

    • Add support for Django 2 and Django 3
    • Test against latest versions of Python (up to 3.10)
    • Stop testing for Django older than 1.8 and Python
    • Stop testing against Python 3.3 to 3.5
    • Change tests infrastructure (Use Github Actions instead of Travis CI and migrate to pytest instead of nose)
    • Add support for Celery 5 (#513)
    • Add new async backend - Dramatiq (trough django-dramatiq) (#527)
    • cachefile_storage now accepts callable (#525)
    • Documentation fixes
    • Fixes LazyImageCacheFile generating the wrong size image (#326)
    • Fixes pickle serialization to help S3 storage (#437, #451)
    Source code(tar.gz)
    Source code(zip)
    django-imagekit-4.1.0.tar.gz(61.23 KB)
    django_imagekit-4.1.0-py2.py3-none-any.whl(42.25 KB)
  • 4.0.2(Nov 20, 2017)

  • 4.0.1(Jul 17, 2017)

    It's a bugfix release. It includes:

    • Fix performance regression for Django >= 1.7 in ImageKit 4.0 (#417)
    • Documentations fixes (#414, #415)

    Full changelog https://github.com/matthewwithanm/django-imagekit/compare/4.0...4.0.1

    Source code(tar.gz)
    Source code(zip)
  • 4.0(Mar 2, 2017)

    This is major version which will drop compatibility with old Python and Django versions.

    • Supported Python versions are: 2.7, 3.3, 3.4, 3.5
    • Supported Django Versions are: 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 1.10, 1.11

    Upgrading from 3.x

    Except from dropping support from older Python and Django versions there are no major changes in the API and most users will do not need to change anything in their code in order to upgrade from 3.x to 4.0. Still you can look down for Backward incompatible changes

    Changes since 3.3

    Full changelog https://github.com/matthewwithanm/django-imagekit/compare/3.3...4.0

    Highlights

    • Add support for Django 1.10 and 1.11
    • Move imagekit.templatetags.compat outside of imagekit.templatetags (Fixes #330, #331 and #352)
    • Include the test suite in the sourcetarball but do not install it. It can be used by distribution packages during build time (#363)
    • Various tests improvements:
      • Replace Lenna image in tests with a truly free alternative (#364)
      • Tests no longer leave junk (Fixes #382)
    • honor post_save's update_fields and only fire the source_saved signal when needed (#390)
    • Close the file only if it has been opened locally (Fixes #404)
    • autodiscover works with AppConfig (#412)
    • Add wheels support (#411)
    • Do not try south modelinspector when not needed (Fixes #408)
    • Improve caching (Fixes #399 #402)

    Backward incompatible changes

    Most of the changes probably will not affect you but still there are changes that can affect you:

    • If you import something from imagekit.templatetags.compat (it's internal API and you should not import anything from there) then you need to fix your imports because this module is now moved to imagekit.compat
    • If you have set IMAGEKIT_CACHE_BACKEND and rely on TIMEOUT defined there it will no longer use that value. Now by default in production (when DEBUG = False) timeout will be None which means forever. If you want to change this value you need to set IMAGEKIT_CACHE_TIMEOUT
    Source code(tar.gz)
    Source code(zip)
    django-imagekit-4.0.tar.gz(61.86 KB)
    django_imagekit-4.0-py2.py3-none-any.whl(45.85 KB)
Django app for handling the server headers required for Cross-Origin Resource Sharing (CORS)

django-cors-headers A Django App that adds Cross-Origin Resource Sharing (CORS) headers to responses. This allows in-browser requests to your Django a

Adam Johnson 4.8k Jan 03, 2023
Django app for building dashboards using raw SQL queries

django-sql-dashboard Django app for building dashboards using raw SQL queries Brings a useful subset of Datasette to Django. Currently only works with

Simon Willison 383 Jan 06, 2023
Yet another Django audit log app, hopefully the simplest one.

django-easy-audit Yet another Django audit log app, hopefully the easiest one. This app allows you to keep track of every action taken by your users.

Natán 510 Jan 02, 2023
Reusable workflow library for Django

django-viewflow Viewflow is a lightweight reusable workflow library that helps to organize people collaboration business logic in django applications.

Viewflow 2.3k Jan 08, 2023
Django Livre Bank

Django Livre Bank Projeto final da academia Construdelas. API de um banco fictício com clientes, contas e transações. Integrantes da equipe Bárbara Sa

Cecília Costa 3 Dec 22, 2021
🗂️ 🔍 Geospatial Data Management and Search API - Django Apps

Geospatial Data API in Django Resonant GeoData (RGD) is a series of Django applications well suited for cataloging and searching annotated geospatial

Resonant GeoData 53 Nov 01, 2022
Developer-friendly asynchrony for Django

Django Channels Channels augments Django to bring WebSocket, long-poll HTTP, task offloading and other async support to your code, using familiar Djan

Django 5.5k Jan 06, 2023
English dictionary using Django based on freecodecamp

English Dictionary Hi there, i made this english dictionary using Django based on freecodecamp.org tutorial :) Table of Contents Preview Technologies

Aline Alencar 3 May 09, 2022
A Django based shop system

django-SHOP Django-SHOP aims to be a the easy, fun and fast e-commerce counterpart to django-CMS. Here you can find the full documentation for django-

Awesto 2.9k Dec 30, 2022
System checks for your project's environment.

django-version-checks System checks for your project's environment. Requirements Python 3.6 to 3.9 supported. Django 2.2 to 3.2 supported. Are your te

Adam Johnson 33 Dec 22, 2022
Store model history and view/revert changes from admin site.

django-simple-history django-simple-history stores Django model state on every create/update/delete. This app supports the following combinations of D

Jazzband 1.8k Jan 06, 2023
Modular search for Django

Haystack Author: Daniel Lindsley Date: 2013/07/28 Haystack provides modular search for Django. It features a unified, familiar API that allows you to

Haystack Search 3.4k Jan 08, 2023
Django + AWS Elastic Transcoder

Django Elastic Transcoder django-elastic-transcoder is an Django app, let you integrate AWS Elastic Transcoder in Django easily. What is provided in t

StreetVoice 66 Dec 14, 2022
Django-Docker - Django Installation Guide on Docker

Guía de instalación del Framework Django en Docker Introducción: Con esta guía p

Victor manuel torres 3 Dec 02, 2022
A Django Demo Project of Students Management System

Django_StudentMS A Django Demo Project of Students Management System. From NWPU Seddon for DB Class Pre. Seddon simplify the code in 2021/10/17. Hope

2 Dec 08, 2021
A blog app powered by python-django

Django_BlogApp This is a blog app powered by python-django Features Add and delete blog post View someone else blog Can add comment to that blog And o

Manish Jalui 1 Sep 12, 2022
Generate generic activity streams from the actions on your site. Users can follow any actors' activities for personalized streams.

Django Activity Stream What is Django Activity Stream? Django Activity Stream is a way of creating activities generated by the actions on your site. I

Justin Quick 2.1k Dec 29, 2022
Repo for All the Assignments I have to submit for Internship Application !😅

Challenges Repository for All the Assignments I have to submit for Internship Application ! 😅 As You know, When ever We apply for an Internship, They

keshav Sharma 1 Sep 08, 2022
Django CacheMiddleware has a multi-threading issue with pylibmc

django-pylibmc-bug Django CacheMiddleware has a multi-threading issue with pylibmc. CacheMiddleware shares a thread-unsafe cache object with many thre

Iuri de Silvio 1 Oct 19, 2022
webfest Django project @innovaccer

inno-doctor webfest Django project @innovaccer setup guide create new directory for project clone the repo with url into the directory make sure pytho

Rohit sahu 6 Oct 28, 2022