Giter Site home page Giter Site logo

easy-thumbnails's Issues

Fix low level example in README

Imports are incorrect

recommend get_thumbnailer instead of using Thumbnailer instance directly: For pythonic thumbnail generation, the easy way is to create your thumbnailer instance with get_thumbnailer.

How to change storage in template?

I have image field:
image = models.ImageField(upload_to='programos/%Y/%m/%d', storage=uploads_storage)

storage point to other folder than MEDIA_* settings. How can I specify in template, what storage should be used?

Migration error

First time I tried to use the app. Migrate gives me this error:

_mysql_exceptions.OperationalError: (1170, "BLOB/TEXT column 'pickle' used in key specification without a key length")

Thumbnail filename

Hi.

I create image with something like this:
{% thumbnail author.images.all.0.image 100x50 %}

... and I get:
/static/images/authors/thumbs/QQbo72SE.jpg.100x50_q85.jpg

Shouldn't I get something like:
/static/images/players/thumbs/QQbo72SE_100x50_q85.jpg

... without first .jpg.?

(I check before if there are images present)

Thank you,

Kind regards.

Wrong arguments passed to get_source_cache

diff --git a/easy_thumbnails/files.py b/easy_thumbnails/files.py
index 763ad13..f362c2c 100644
--- a/easy_thumbnails/files.py
+++ b/easy_thumbnails/files.py
@@ -334,7 +334,7 @@ class ThumbnailerFieldFile(FieldFile, Thumbnailer):
         
         """
         super(ThumbnailerFieldFile, self).save(name, content, *args, **kwargs)
-        self.get_source_cache(self, create=True, update=True)
+        self.get_source_cache(create=True, update=True)
 
     def delete(self, *args, **kwargs):
         """

Migration 0010 fails, when using MySQL

Hey,

the south migration with mysql fails with the current alpha-12 version.

easy_thumbnails:0010_rename_storage
! Error found during real run of migration! Aborting.

[...]
File "/home/daniel/.virtualenvs/myenv/lib/python2.6/site-packages/easy_thumbnails/migrations/0010_rename_storage.py", line 13, in forwards
db.drop_foreign_key('easy_thumbnails_source', 'storage_new_id')
[...]
raise ValueError("Cannot find a FOREIGN KEY constraint on table %s, column %s" % (table_name, column))
ValueError: Cannot find a FOREIGN KEY constraint on table easy_thumbnails_source, column storage_new_id

Remove the storage class

It's a pain, and an edge case which has caused headaches and complex code.

Replace with a hash of the storage class module name as a CharField on the File base model class (this will be on the Source and Thumbnail models then).

null value in column "storage_id" violates not-null constraint

Hey there,

an upgrade from alpha 3 to alpha 12 broke some tests for me. When saving a new Thumbnail an IntegrityError is raised: http://gist.github.com/609702

The field definition is quite simple:

thumbnail_photo = ThumbnailerImageField(
    upload_to="product_photos",
    resize_source={
        'size': (128, 128),
        'quality': 85
    }
)

Am I missing something? In that case I think the error should be caught earlier.

Cheers,
Pascal

Low-Level Usage examples don't seem to work

I get ImportErrors with from easy_thumbnails import Thumbnailer and from easy_thumbnails import ThumbnailFile -- had to update to from easy_thumbnails.files import ...

Also,

source = ThumbnailFile('animals/aarvark.jpg')
square_thumbnail(source)

Gives me:

Traceback (most recent call last):
...
  File ".../easy_thumbnails/files.py", line 318, in get_thumbnail
    thumbnail = self.generate_thumbnail(thumbnail_options)
  File ".../easy_thumbnails/files.py", line 234, in generate_thumbnail
    thumbnail_image = engine.process_image(self.image, thumbnail_options)
  File ".../easy_thumbnails/files.py", line 356, in _image
    self.open()
  File ".../django/core/files/base.py", line 110, in open
    raise ValueError("The file cannot be reopened.")
ValueError: The file cannot be reopened.

Question - how do I create a processor?

I'm trying to make a processor that squares images in a fashion such that you specify a width, and if an image is wider than tall, the width is set to your "width" and the shorter height is centered vertically and filled with white space. The same goes for taller than wide images. I am using PIL for this functionality but I can't figure out what type to return.

I've tried to use this to find out:

def make_square(image, size):
    raise TypeError(type(image))

but no exception is output. Are exceptions completely trapped, or am I doing something wrong. I have DEBUG = TRUE in settings.py and I have "myproject.image_processors.make_square" in settings.THUMBNAIL_PROCESSORS.

files.thumnailer.get_thumbnail fails when re-saving models because it makes a hash of path stored in model

I'm trying to use easy-thumbnails to pre-generate a thumbnail for an image in one of my models.
To do so, I've created a custom save method for my model:

class Picture(models.Model):
img = models.ImageField(upload_to='pics/%Y/%B/%d/' , max_length=256,)
thumb = ThumbnailerImageField(upload_to='thumbs/%Y/%B/%d/',
resize_source = dict(size=(120,90), crop=True), blank=True, null=True, )
caption = models.CharField(max_length=512)

 def save(self):
     super(Picture, self).save()
     self.thumb = Thumbnailer(self.img.file).get_thumbnail(dict(size=(120, 90), crop=True,))
     super(Picture, self).save()

(thumb has a custom widget)
This works fine at first. But if the caption gets changed and save called again, the thumbnail field changes from a relative path to a system path, ie:
self.img.file pics/2010/June/24/xyz.jpg
becomes the thumb:
thumbs/2010/June/24/xyz.jpg
but if the model is saved again, the thumb becomes:
/home/webby/www/localhost/wc-web/media/pics/2010/June/24/thmb_xyz.jpg.120x90_q85_crop.jpg

This behavior seems to occur in get_thumbnail, based on whether the
if self.thumbnail_exists(filename):
condition triggers.

I'm still trying to figure out why it functions as expected on first save but not second.

can't pickle HASH objects

Been getting the following exception while using django-storages s3boto file storage backend.


Traceback:
File "/Users/gtaylor/.virtualenvs/coursebook/lib/python2.6/site-packages/django/core/handlers/base.py" in get_response
  100.                     response = callback(request, *callback_args, **callback_kwargs)
File "/Users/gtaylor/.virtualenvs/coursebook/lib/python2.6/site-packages/django/contrib/admin/options.py" in wrapper
  239.                 return self.admin_site.admin_view(view)(*args, **kwargs)
File "/Users/gtaylor/.virtualenvs/coursebook/lib/python2.6/site-packages/django/utils/decorators.py" in _wrapped_view
  76.                     response = view_func(request, *args, **kwargs)
File "/Users/gtaylor/.virtualenvs/coursebook/lib/python2.6/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
  69.         response = view_func(request, *args, **kwargs)
File "/Users/gtaylor/.virtualenvs/coursebook/lib/python2.6/site-packages/django/contrib/admin/sites.py" in inner
  190.             return view(request, *args, **kwargs)
File "/Users/gtaylor/.virtualenvs/coursebook/lib/python2.6/site-packages/django/utils/decorators.py" in _wrapper
  21.             return decorator(bound_func)(*args, **kwargs)
File "/Users/gtaylor/.virtualenvs/coursebook/lib/python2.6/site-packages/django/utils/decorators.py" in _wrapped_view
  76.                     response = view_func(request, *args, **kwargs)
File "/Users/gtaylor/.virtualenvs/coursebook/lib/python2.6/site-packages/django/utils/decorators.py" in bound_func
  17.                 return func(self, *args2, **kwargs2)
File "/Users/gtaylor/.virtualenvs/coursebook/lib/python2.6/site-packages/django/db/transaction.py" in _commit_on_success
  299.                     res = func(*args, **kw)
File "/Users/gtaylor/.virtualenvs/coursebook/lib/python2.6/site-packages/django/contrib/admin/options.py" in change_view
  895.                 self.save_model(request, new_object, form, change=True)
File "/Users/gtaylor/.virtualenvs/coursebook/lib/python2.6/site-packages/django/contrib/admin/options.py" in save_model
  597.         obj.save()
File "/Users/gtaylor/.virtualenvs/coursebook/lib/python2.6/site-packages/django/db/models/base.py" in save
  435.         self.save_base(using=using, force_insert=force_insert, force_update=force_update)
File "/Users/gtaylor/.virtualenvs/coursebook/lib/python2.6/site-packages/django/db/models/base.py" in save_base
  500.                         values = [(f, None, (raw and getattr(self, f.attname) or f.pre_save(self, False))) for f in non_pks]
File "/Users/gtaylor/.virtualenvs/coursebook/lib/python2.6/site-packages/django/db/models/fields/files.py" in pre_save
  255.             file.save(file.name, file, save=False)
File "/Users/gtaylor/.virtualenvs/coursebook/lib/python2.6/site-packages/easy_thumbnails/files.py" in save
  418.                                                     **kwargs)
File "/Users/gtaylor/.virtualenvs/coursebook/lib/python2.6/site-packages/easy_thumbnails/files.py" in save
  368.         self.get_source_cache(create=True, update=True)
File "/Users/gtaylor/.virtualenvs/coursebook/lib/python2.6/site-packages/easy_thumbnails/files.py" in get_source_cache
  319.             storage=self.source_storage, name=self.name)
File "/Users/gtaylor/.virtualenvs/coursebook/lib/python2.6/site-packages/easy_thumbnails/models.py" in get_file
  23.             storage = Storage.objects.get_storage(storage)
File "/Users/gtaylor/.virtualenvs/coursebook/lib/python2.6/site-packages/easy_thumbnails/models.py" in get_storage
  11.         pickled = pickle.dumps(storage)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in dumps
  1366.     Pickler(file, protocol).dump(obj)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in dump
  224.         self.save(obj)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in save
  331.         self.save_reduce(obj=obj, *rv)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in save_reduce
  419.             save(state)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in save
  286.             f(self, obj) # Call unbound method with explicit self
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in save_dict
  649.         self._batch_setitems(obj.iteritems())
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in _batch_setitems
  663.                 save(v)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in save
  331.         self.save_reduce(obj=obj, *rv)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in save_reduce
  419.             save(state)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in save
  286.             f(self, obj) # Call unbound method with explicit self
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in save_dict
  649.         self._batch_setitems(obj.iteritems())
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in _batch_setitems
  663.                 save(v)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in save
  286.             f(self, obj) # Call unbound method with explicit self
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in save_inst
  725.         save(stuff)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in save
  286.             f(self, obj) # Call unbound method with explicit self
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in save_dict
  649.         self._batch_setitems(obj.iteritems())
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in _batch_setitems
  663.                 save(v)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in save
  286.             f(self, obj) # Call unbound method with explicit self
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in save_inst
  725.         save(stuff)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in save
  286.             f(self, obj) # Call unbound method with explicit self
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in save_dict
  649.         self._batch_setitems(obj.iteritems())
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in _batch_setitems
  663.                 save(v)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in save
  286.             f(self, obj) # Call unbound method with explicit self
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in save_inst
  725.         save(stuff)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in save
  286.             f(self, obj) # Call unbound method with explicit self
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in save_dict
  649.         self._batch_setitems(obj.iteritems())
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in _batch_setitems
  663.                 save(v)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py" in save
  306.                 rv = reduce(self.proto)
File "/Users/gtaylor/.virtualenvs/coursebook/bin/../lib/python2.6/copy_reg.py" in _reduce_ex
  70.             raise TypeError, "can't pickle %s objects" % base.__name__

Exception Type: TypeError at /admin/profile/coursebookid/3/
Exception Value: can't pickle HASH objects

Thumbnails have MIME type application/octet-stream on CloudFiles

Browsers can have problems with that.

Using latest django-storages from http://bitbucket.org/smileychris/django-storages/, latest python-cloudfiles from git://github.com/rackspace/python-cloudfiles.git, latest easy-thumbnails from git://github.com/SmileyChris/easy-thumbnails.git. As of 2010-03-08.

My proposed solution:

--- a/easy_thumbnails/files.py
+++ b/easy_thumbnails/files.py
@@ -1,23 +1,24 @@
 from PIL import Image
-from django.core.files.base import File, ContentFile
+from django.core.files.base import File
+from django.core.files.uploadedfile import SimpleUploadedFile
 from django.core.files.storage import get_storage_class, default_storage
 from django.db.models.fields.files import ImageFieldFile, FieldFile
 from django.utils.html import escape
 from django.utils.safestring import mark_safe
 from easy_thumbnails import engine, models, utils
 import datetime
 import os
-
+import mimetypes
 
 DEFAULT_THUMBNAIL_STORAGE = get_storage_class(
                                         utils.get_setting('DEFAULT_STORAGE'))()
 
 
 def get_thumbnailer(source, relative_name=None):
     """
     Get a thumbnailer for a source file.
     
     """
     if isinstance(source, Thumbnailer):
         return source
     elif isinstance(source, FieldFile):
@@ -181,27 +182,29 @@ class Thumbnailer(File):
     def generate_thumbnail(self, thumbnail_options):
         """
         Return a ``ThumbnailFile`` containing a thumbnail image.
         
         The thumbnail image is generated using the ``thumbnail_options``
         dictionary.
         
         """
         thumbnail_image = engine.process_image(self.image, thumbnail_options)
         quality = thumbnail_options.get('quality', self.thumbnail_quality)
         data = engine.save_image(thumbnail_image, quality=quality).read()
 
         filename = self.get_thumbnail_name(thumbnail_options)
-        thumbnail = ThumbnailFile(filename, ContentFile(data),
+        content_type = mimetypes.guess_type(filename)[0]
+        file = SimpleUploadedFile(filename, data, content_type)
+        thumbnail = ThumbnailFile(filename, file,
                                   storage=self.thumbnail_storage)
         thumbnail.image = thumbnail_image

thumbnail_storage is None by default

In [6]: l.image.generate_thumbnail({'size':(50,50)})
---------------------------------------------------------------------------
        Traceback (most recent call last)

/home/pete/sandbox/cloudfiles/project/ in ()

/home/pete/sandbox/cloudfiles/src/easy-thumbnails/easy_thumbnails/files.py in generate_thumbnail(self, thumbnail_options)
    176         filename = self.get_thumbnail_name(thumbnail_options)
    177         thumbnail = ThumbnailFile(filename, ContentFile(data),
--> 178                                   storage=self.thumbnail_storage)
    179         thumbnail.image = thumbnail_image
    180         thumbnail._committed = False

: 'ThumbnailerImageFieldFile' object has no attribute 'thumbnail_storage'

This fixes the issue:

diff --git a/easy_thumbnails/fields.py b/easy_thumbnails/fields.py
index d49af50..ee77d2e 100644
--- a/easy_thumbnails/fields.py
+++ b/easy_thumbnails/fields.py
@@ -16,10 +16,11 @@ class ThumbnailerField(FileField):
     def __init__(self, *args, **kwargs):
         # Arguments not explicitly defined so that the normal ImageField
         # positional arguments can be used.
-        self.thumbnail_storage = kwargs.pop('thumbnail_storage', None)
         
         super(ThumbnailerField, self).__init__(*args, **kwargs)
 
+        self.thumbnail_storage = kwargs.pop('thumbnail_storage', self.storage)
+
     def south_field_triple(self):
         """
         Return a suitable description of this field for South.

Tests fail if `THUMBNAIL_BASEDIR` is set

======================================================================
FAIL: testTag (easy_thumbnails.tests.templatetags.ThumbnailTagTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/.../easy_thumbnails/tests/templatetags.py", line 142, in testTag
    self.verify_thumbnail((240, 180), expected)
  File "/.../easy_thumbnails/tests/templatetags.py", line 50, in verify_thumbnail
    'Thumbnail file %r not found' % expected_filename)
AssertionError: Thumbnail file 'thumbs/test.jpg.240x240_q85.jpg' not found

======================================================================
FAIL: test_delete (easy_thumbnails.tests.fields.ThumbnailerFieldTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/.../easy_thumbnails/tests/fields.py", line 44, in test_delete
    self.assertEqual(len(self.storage.listdir('avatars')[1]), 4)
AssertionError: 1 != 4

======================================================================
FAIL: test_delete_thumbnails (easy_thumbnails.tests.fields.ThumbnailerFieldTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/.../easy_thumbnails/tests/fields.py", line 53, in test_delete_thumbnails
    self.assertEqual(len(self.storage.listdir('avatars')[1]), 4)
AssertionError: 1 != 4

----------------------------------------------------------------------
Ran 13 tests in 3.778s

Transparent thumbnails with remote storage backends

I was unable to get thumbnails working for any images that had transparency when using the django-storages s3boto backend. They would work fine on initial generation, but then subsequent loads (when easy-thumbnails was using the cache) would fail.

I added some unit tests trying to pinpoint the problem and I think I might have figured it out with this commit: http://github.com/winhamwr/easy-thumbnails/commit/d1e74f2213909cad39a307cdbda078fa4b4fa21e

I also have some other unit test refactoring/additions in the branch if you're interested. The defaultfs flavor of tests might not be worth adding, but I needed a way to specifically test with my s3 backend while I was trying to mock out the FakeRemoteStorage backend and I figure it might be useful for quickly testing different backends. I didn't add it to easy-thumbnails.tests so I think the default test runner won't pick them up anyway.

Thumbnail folder (not really an issue)

Hi.

Is it possible to save thumbnails into specific folder?

e.g. I have images in /django/images ... but want to have thumbnails in /django/images/thumbs/ ...

Kind regards,

Rok

Field arguments don't work with South

I tried adding a ThumbnailerImageField to my models but there seems to be something wrong with South migrations.

I specified null=True, blank=True and max_length=1024 but none of these end up in South migration file. This might also be a South problem as it doesn't as default values anymore but lacks these in later steps.

I'm using South 0.7 with Django 1.2.

Only constrain one size dimension

I'd like to be able to only define a size constraint for either the width or height. This allows "skyscraper" images to be scaled to fit a specific width but still remain viewable as they extend down vertically.

Right now, the only way to do this is to specify a very large width or height, such at 250x9000.

I propose that specifying 250x0 will allow the image to be as tall as it wants and only constrain the width to 250px. Likewise, setting a width of 0 will no longer constrain the width.

Add dependency to Django >= 1.2

easy-thumbnails, as an emerging library, should require Django 1.2+ and should be explicit about it in the setup.py file.

Filesize

This is a great tool, thanks!

But (always a but ;-). If I run 'Smush It', the images are all optimized up to 50%. Is there any way anyone can optimize this tool for the filesize?

Thanx in advance
Martijn

Caught NameError while rendering: global name 'source' is not defined

Latest verison in repo.
Looks like in file:
easy_thumbnails/files.py
error in :
351 def _image(self):

Environment:
Django Version: 1.2.2
Python Version: 2.6.5

52 :

  1.         result = node.render(context)
    
    File "/home/vprohoda/sites/sp2all/sp2allve/lib/python2.6/site-packages/easy_thumbnails/templatetags/thumbnail.py" in render
  2.         thumbnail = get_thumbnailer(source).get_thumbnail(opts)
    
    File "/home/vprohoda/sites/sp2all/sp2allve/lib/python2.6/site-packages/easy_thumbnails/files.py" in get_thumbnail
  3.     thumbnail = self.generate_thumbnail(thumbnail_options)
    
    File "/home/vprohoda/sites/sp2all/sp2allve/lib/python2.6/site-packages/easy_thumbnails/files.py" in generate_thumbnail
  4.     thumbnail_image = engine.process_image(self.image, thumbnail_options)
    
    File "/home/vprohoda/sites/sp2all/sp2allve/lib/python2.6/site-packages/easy_thumbnails/files.py" in _image
  5.         self._cached_image = engine.generate_source_image(source,
    

Exception Type: TemplateSyntaxError at /sp/15/edit/offers/2002
Exception Value: Caught NameError while rendering: global name 'source' is not defined

LazyObject fools get_thumbnailer

DefaultStorage derives from LazyObject, and so does not test true as an instance of Storage

>>> from django.core.files.storage import default_storage, Storage
>>> isinstance( default_storage, Storage )
False
>>> default_storage
<django.core.files.storage.DefaultStorage object at 0x2ac735da22d0>

margin filter / give Thumbnail file a margin property

the new sorl thumbnail has a margin filter, which is all very nice but requires me to duplicate the size specification.

Would be nice if the ThumbnailFile also knew the requested size so it knew what the margin had to be to make the image centered on the requested size.

Something like:

{% thumbnail model.image "100x100" as im %}
<img src="{{ im.url }}" style="margin:{{ im.margin }}" alt="Image" width="{{ im.width }}" height="{{ im.height }}" />

Preserve fileformat

It would be wonderful to have the ability to preserve the file format when thumbnailing. As far as I can see currently the THUMBNAIL_EXTENSION is used to determine the output format. Now if I have at least one PNG file with transparency which I want to thumbnail, I have to set the output format to PNG for all files which is not ideal since PNGs usually are bigger than jpg files.

My proposal would be to allow setting THUMBNAIL_EXTENSION to None to tell easy-thumbnails to just preserve the format.

Error migrating from scratch with mysql innodb

Migrating forward from scratch with django 1.2, easy-thumbnails 78ce430 and South 1.2 on MySQL with InnoDB fails running 0010_rename_storage and gives this traceback: http://dpaste.com/243358/

The FK error is:

LATEST FOREIGN KEY ERROR
------------------------
100914 12:57:35 Error in foreign key constraint of table dev/easy_thumbnails_source:
there is no index in the table which would contain
the columns as the first columns, or the data types in the
table do not match to the ones in the referenced table
or one of the ON ... SET NULL columns is declared NOT NULL. Constraint:,
CONSTRAINT storage_new_id_refs_id_5cebe21bafd2e07f FOREIGN KEY (storage_new_id) REFERENCES easy_thumbnails_storage (id)

Any plans on storing the image dimensions in the easy_thumbnails models?

As we use the remote storage (CloudFiles) for everything, the easy_thumbnails is only providing the image URLs to the templates and we lose the width/height info, so the designers can't create an accurate placeholders.

My app is surely capable of using PIL to ping the dimensions of source images and store them in its own models, but there seems to be no easy way to do the same with the thumbnails themselves.
And it would be cleaner to handle the dimensions in one place.

Would you see the support for remote-storage image dimensions:

  • proper for general e_t (yours repo)
  • or should I add the support to my clone and sync it with your future commits
  • or this would be best accomplished from the app itself?

Thank you

MEDIA_ROOT is used on the output of a {% thumbnail %}

When using:

{% thumbnail some_thumbnailerimagefield_instance 150x150 %}

The output is:

d:/some/path/to/my/images/directory/image.jpg.150x150_q85.jpg

Why would this be? At what point would I ever want to output the MEDIA_ROOT into my web page?

Compatibility with sorl-thumbnail

This template tag is nearly a drop-in replacement for sorl.thumbnail except the name of the template tag is "thumbnails" instead of sorl.thumbnail's "thumbnail"

Is this intentional? It seems having a drop-in replacement for sorl-thumbnail would increase adoption rate.

We're storing the same 40 bytes long storage_id hash several million times

As the primary key of Storage is the 40 bytes SHA1 hash and both Source and Thumbnail models reference it, there's a huge data redundancy and I expect also the performance loss. Why was that necessary instead of a simple integer?

The fact we're using only one type of storage (mosso CloudFiles) throughout the entire app is making it only a bit worse... :)

Cannot handle gif or png images from CloudFiles

Hi Chris,

I'm using easy thumbnails with Rackspace CloudFiles and for jpeg images it works very well.

The problem is when I deal with gif or png images. I dig into the problem and found that PIL expects a file like object that support tell and seek methods and the Storage object from cloudfiles API do not have these methods.

It seems that the jpeg library do not use these methods but gif and png lib does.

The problem is when opening the image on the "_image" method of Thumbnailer class on the files module:

    self._cached_image = Image.open(self)

Do you faced similar problem? I don't know if rackspace cloudfiles api can have the tell and seek methods. Maybe the file can be opened a different way in this case, what do you think?

First time {% thumbnail .... %} is called it fails with IntegrityError

IntegrityError: null value in column "storage_id" violates not-null constraint

exception is raised (with THUMBNAIL_DEBUG = True) when first attempt to create thumbnail is made. This is due to lack of 'storage' in kwargs passed to get_or_create in models.py->FileManager->get_file

Traceback:

File "/opt/path/to/my/app/parts/easy-thumbnails/easy_thumbnails/templatetags/thumbnail.py", line 80, in render
  thumbnail = get_thumbnailer(source).get_thumbnail(opts)
File "/opt/path/to/my/app/parts/easy-thumbnails/easy_thumbnails/files.py", line 334, in get_thumbnail
  self.get_thumbnail_cache(filename, create=True, update=True)
File "/opt/path/to/my/app/parts/easy-thumbnails/easy_thumbnails/files.py", line 376, in get_thumbnail_cache
  source = self.get_source_cache(create=True)
File "/opt/path/to/my/app/parts/easy-thumbnails/easy_thumbnails/files.py", line 369, in get_source_cache
  storage=self.source_storage, name=self.name)
File "/opt/path/to/my/app/parts/easy-thumbnails/easy_thumbnails/models.py", line 16, in get_file
  object, created = self.get_or_create(**kwargs)
File "/opt/path/to/my/app/parts/django/django/db/models/manager.py", line 123, in get_or_create
  return self.get_query_set().get_or_create(**kwargs)
File "/opt/path/to/my/app/parts/django/django/db/models/query.py", line 343, in get_or_create
    raise e
IntegrityError: null value in column "storage_id" violates not-null constraint

Corresponding SQL is:

INSERT INTO "easy_thumbnails_source" ("storage_hash", "name", "modified") VALUES (E'df2a8819fc7f348e9715cca951e8e5df', E'uploads/PA035971_.jpg', E'2010-10-05 21:43:

23.439094')

ImportError fix...

Sometimes (usually if you install PIL via easy_install I think) the Python Imaging Lib gets installed in the root namespace so doing from PIL import Image is not working...

Basically I searched/replaced every instance of from PIL import Image with:

try:
    from PIL import Image
except ImportError:
    import Image

and so far it appears to have successfully fixed the issue... (that issue is also discussed in the django bug tracker here: http://code.djangoproject.com/ticket/6054 ) I think they came to the same conclusion...

Wrong dimensions

Original image:
2400px × 3620px

I call:
{% thumbnail entry.image 110x1100 sharpen quality=90 %}
I get:
109px × 165px

I call:
{% thumbnail entry.image 110x165 sharpen crop quality=90 %}
I get:
109px × 165px

There is no way to make it 110px wide :(

Unable to pickle Cloud Files storage object from django_storages

My model looks like this:

from easy_thumbnails.fields import ThumbnailerImageField
from backends.mosso import CloudFilesStorage, cloudfiles_upload_to

cloudfiles_storage = CloudFilesStorage()

class CloudFilesImage(models.Model):
    image = ThumbnailerImageField(storage=cloudfiles_storage,
                                  upload_to=cloudfiles_upload_to)

Here is the traceback:

Environment:

Request Method: POST
Request URL: http://127.0.0.1:8000/admin/images/cloudfilesimage/add/
Django Version: 1.1.1
Python Version: 2.5.2
Installed Applications:
['django.contrib.auth',
 'django.contrib.admin',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'easy_thumbnails',
 'images']
Installed Middleware:
('django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware')


Traceback:
File "/home/pete/sandbox/cloudfiles/lib/python2.5/site-packages/django/core/handlers/base.py" in get_response
  92.                 response = callback(request, *callback_args, **callback_kwargs)
File "/home/pete/sandbox/cloudfiles/lib/python2.5/site-packages/django/contrib/admin/sites.py" in root
  490.                 return self.model_page(request, *url.split('/', 2))
File "/home/pete/sandbox/cloudfiles/lib/python2.5/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
  44.         response = view_func(request, *args, **kwargs)
File "/home/pete/sandbox/cloudfiles/lib/python2.5/site-packages/django/contrib/admin/sites.py" in model_page
  509.         return admin_obj(request, rest_of_url)
File "/home/pete/sandbox/cloudfiles/lib/python2.5/site-packages/django/contrib/admin/options.py" in __call__
  1092.             return self.add_view(request)
File "/home/pete/sandbox/cloudfiles/lib/python2.5/site-packages/django/db/transaction.py" in _commit_on_success
  240.                 res = func(*args, **kw)
File "/home/pete/sandbox/cloudfiles/lib/python2.5/site-packages/django/contrib/admin/options.py" in add_view
  734.                 self.save_model(request, new_object, form, change=False)
File "/home/pete/sandbox/cloudfiles/lib/python2.5/site-packages/django/contrib/admin/options.py" in save_model
  557.         obj.save()
File "/home/pete/sandbox/cloudfiles/lib/python2.5/site-packages/django/db/models/base.py" in save
  410.         self.save_base(force_insert=force_insert, force_update=force_update)
File "/home/pete/sandbox/cloudfiles/lib/python2.5/site-packages/django/db/models/base.py" in save_base
  483.                     values = [(f, f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, True))) for f in meta.local_fields if not isinstance(f, AutoField)]
File "/home/pete/sandbox/cloudfiles/lib/python2.5/site-packages/django/db/models/fields/files.py" in pre_save
  252.             file.save(file.name, file, save=False)
File "/home/pete/sandbox/cloudfiles/src/easy-thumbnails/easy_thumbnails/files.py" in save
  376.                                                     **kwargs)
File "/home/pete/sandbox/cloudfiles/src/easy-thumbnails/easy_thumbnails/files.py" in save
  337.         self.get_source_cache(create=True, update=True)
File "/home/pete/sandbox/cloudfiles/src/easy-thumbnails/easy_thumbnails/files.py" in get_source_cache
  290.             storage=self.source_storage, name=self.name)
File "/home/pete/sandbox/cloudfiles/src/easy-thumbnails/easy_thumbnails/models.py" in get_file
  23.             storage = Storage.objects.get_storage(storage)
File "/home/pete/sandbox/cloudfiles/src/easy-thumbnails/easy_thumbnails/models.py" in get_storage
  11.         pickled = pickle.dumps(storage)
File "/usr/lib/python2.5/pickle.py" in dumps
  1366.     Pickler(file, protocol).dump(obj)
File "/usr/lib/python2.5/pickle.py" in dump
  224.         self.save(obj)
File "/usr/lib/python2.5/pickle.py" in save
  331.         self.save_reduce(obj=obj, *rv)
File "/usr/lib/python2.5/pickle.py" in save_reduce
  419.             save(state)
File "/usr/lib/python2.5/pickle.py" in save
  286.             f(self, obj) # Call unbound method with explicit self
File "/usr/lib/python2.5/pickle.py" in save_dict
  649.         self._batch_setitems(obj.iteritems())
File "/usr/lib/python2.5/pickle.py" in _batch_setitems
  663.                 save(v)
File "/usr/lib/python2.5/pickle.py" in save
  331.         self.save_reduce(obj=obj, *rv)
File "/usr/lib/python2.5/pickle.py" in save_reduce
  419.             save(state)
File "/usr/lib/python2.5/pickle.py" in save
  286.             f(self, obj) # Call unbound method with explicit self
File "/usr/lib/python2.5/pickle.py" in save_dict
  649.         self._batch_setitems(obj.iteritems())
File "/usr/lib/python2.5/pickle.py" in _batch_setitems
  663.                 save(v)
File "/usr/lib/python2.5/pickle.py" in save
  286.             f(self, obj) # Call unbound method with explicit self
File "/usr/lib/python2.5/pickle.py" in save_inst
  725.         save(stuff)
File "/usr/lib/python2.5/pickle.py" in save
  286.             f(self, obj) # Call unbound method with explicit self
File "/usr/lib/python2.5/pickle.py" in save_dict
  649.         self._batch_setitems(obj.iteritems())
File "/usr/lib/python2.5/pickle.py" in _batch_setitems
  663.                 save(v)
File "/usr/lib/python2.5/pickle.py" in save
  286.             f(self, obj) # Call unbound method with explicit self
File "/usr/lib/python2.5/pickle.py" in save_inst
  725.         save(stuff)
File "/usr/lib/python2.5/pickle.py" in save
  286.             f(self, obj) # Call unbound method with explicit self
File "/usr/lib/python2.5/pickle.py" in save_dict
  649.         self._batch_setitems(obj.iteritems())
File "/usr/lib/python2.5/pickle.py" in _batch_setitems
  663.                 save(v)
File "/usr/lib/python2.5/pickle.py" in save
  306.                 rv = reduce(self.proto)
File "/usr/lib/python2.5/copy_reg.py" in _reduce_ex
  76.             raise TypeError("a class that defines __slots__ without "

Exception Type: TypeError at /admin/images/cloudfilesimage/add/
Exception Value: a class that defines __slots__ without defining __getstate__ cannot be pickled

test_crop_smart test failure

test_crop_smart test fails on Python 2.6, PIL 1.1.7, easy-thumbnails master, and Django 1.2.


Installed 62 object(s) from 1 fixture(s)
....F.
======================================================================
FAIL: test_crop_smart (easy_thumbnails.tests.processors.ScaleAndCropTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/gtaylor/Documents/workspace/coursebook/bundled/easy-thumbnails/easy_thumbnails/tests/processors.py", line 85, in test_crop_smart
    self.assertImagesEqual(smart_crop, expected)
  File "/Users/gtaylor/Documents/workspace/coursebook/bundled/easy-thumbnails/easy_thumbnails/tests/processors.py", line 19, in assertImagesEqual
    (msg or 'The two images were not identical')
AssertionError: The two images were not identical

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

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.