1 | from django.db import models
|
---|
2 | from django.dispatch import dispatcher
|
---|
3 | from django.db.models import signals
|
---|
4 | from django.utils.functional import curry
|
---|
5 |
|
---|
6 | from django.conf import settings
|
---|
7 | import os
|
---|
8 |
|
---|
9 | def default_thumbnalaizer(src, width=100, height=100):
|
---|
10 | """
|
---|
11 | Make a thumbnail from src file,
|
---|
12 | return value should be raw_field compatatible
|
---|
13 | """
|
---|
14 | import Image
|
---|
15 |
|
---|
16 | try:
|
---|
17 | from cStringIO import StringIO
|
---|
18 | except ImportError:
|
---|
19 | from StringIO import StringIO
|
---|
20 |
|
---|
21 | img_src = Image.open(src)
|
---|
22 | img_src.thumbnail((width, height))
|
---|
23 |
|
---|
24 | ret = StringIO()
|
---|
25 | img_src.save(fp=ret, format=img_src.format)
|
---|
26 | return ret.getvalue()
|
---|
27 |
|
---|
28 | class ThumbnailField(models.ImageField):
|
---|
29 | def __init__(self, thumb_for, thumb_func=default_thumbnalaizer, **kwargs):
|
---|
30 | kwargs['blank']=True
|
---|
31 | super(ThumbnailField, self).__init__(**kwargs)
|
---|
32 | self.thumb_for = thumb_for
|
---|
33 | self.thumb_func = thumb_func
|
---|
34 | self._cached_attr = '__cached_image_%s' % self.get_attname()
|
---|
35 |
|
---|
36 | def contribute_to_class(self, cls, name):
|
---|
37 | super(ThumbnailField, self).contribute_to_class(cls, name)
|
---|
38 | setattr(cls, 'force_%s_rethumb' % self.name, curry(self.force_rethumb))
|
---|
39 | dispatcher.connect(self.post_init, signal=signals.post_init, sender=cls)
|
---|
40 |
|
---|
41 | def pre_save(self, instance, add):
|
---|
42 | cached = getattr(instance, self._cached_attr)
|
---|
43 | image = getattr(instance, self.thumb_for)
|
---|
44 | thumb = getattr(instance, self.get_attname())
|
---|
45 |
|
---|
46 | if add or cached != image or (image and not thumb):
|
---|
47 | self.force_rethumb(instance)
|
---|
48 | return super(ThumbnailField, self).pre_save(instance, add)
|
---|
49 |
|
---|
50 | def post_init(self, instance):
|
---|
51 | image = getattr(instance, self.thumb_for)
|
---|
52 | setattr(instance, self._cached_attr, image)
|
---|
53 |
|
---|
54 | def force_rethumb(self, instance):
|
---|
55 | image = getattr(instance, self.thumb_for)
|
---|
56 | filename = self.get_filename(image)
|
---|
57 | raw_field = self.thumb_func(os.path.join(settings.MEDIA_ROOT, image))
|
---|
58 | instance._save_FIELD_file(self, filename, raw_field, save=False)
|
---|
59 | setattr(instance, self._cached_attr, image)
|
---|
60 | ##
|
---|
61 | ## Just an example usage
|
---|
62 | ##
|
---|
63 | # class Picture(models.Model):
|
---|
64 | # image = models.ImageField(upload_to='images')
|
---|
65 | # thumb = ThumbnailField(thumb_for='image', upload_to='images/thumbs')
|
---|
66 | #
|
---|
67 | # def thumbnail(self):
|
---|
68 | # return '<img src="%s" />' % self.get_thumb_url()
|
---|
69 | # thumbnail.allow_tags=True
|
---|
70 | #
|
---|
71 | # from django.contrib import admin
|
---|
72 | #
|
---|
73 | # class PictureAdmin(admin.ModelAdmin):
|
---|
74 | # list_display=('thumbnail',)
|
---|
75 | #
|
---|
76 | # admin.site.register(Picture, PictureAdmin)
|
---|
77 | #
|
---|