| 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 |
# |
|---|