I have been tortured by this problem for a whole week. I really hope a superman can help me solve it. I tried to create a new file field called "ThumbnailImage Field". The following is my model.py:
The following is my ThumnailImageFi eld.py which stored under /cn/han/:
Finally here is my template called items_list.html :
Code:
from django.db import models
from django.contrib import admin
from cn.han import ThumbnailImageField
from django.db.models.fields.files import ImageField, ImageFieldFile
# Create your models here.
class Item(models.Model):
name = models.CharField(max_length=250)
description = models.TextField()
class Meta:
ordering = ['name']
def __unicode__(self):
return self.name
@models.permalink
def get_absolute_url(self):
return ('item_detail', None, {'object_id': self.id})
class Photo(models.Model):
item = models.ForeignKey(Item)
title = models.CharField(max_length=100)
image = ThumbnailImageField(upload_to='photos')
#TypeError here: 'module' object is not callable.
caption = models.CharField(max_length=250, blank=True)
class Meta:
ordering = ['title']
def __unicode__(self):
return self.title
@models.permalink
def get_absolute_url(self):
return ('photo_detail', None, {'object_id': self.id})
class PhotoInline(admin.StackedInline):
model = Photo
class ItemAdmin(admin.ModelAdmin):
inlines = [PhotoInline]
admin.site.register(Item, ItemAdmin)
admin.site.register(Photo)
Code:
from django.db.models.fields.files import ImageField, ImageFieldFile
from PIL import Image
import os
from django.db import models
def _add_thumb(s):
"""
Modifies a string (filename, URL) containing an image filename, to insert
'.thumb' before the file extension (which is changed to be '.jpg').
"""
parts = s.split(".")
parts.insert(-1, "thumb")
if parts[-1].lower() not in ['jpeg', 'jpg']:
parts[-1] = 'jpg'
return ".".join(parts)
class ThumbnailImageField(ImageField):
"""
Behaves like a regular ImageField, but stores an extra (JPEG) thumbnail
image, providing get_FIELD_thumb_url() and get_FIELD_thumb_filename().
Accepts two additional, optional arguments: thumb_width and thumb_height,
both defaulting to 128 (pixels). Resizing will preserve aspect ratio while
staying inside the requested dimensions; see PIL's Image.thumbnail()
method documentation for details.
"""
def __init__(self, thumb_width=128, thumb_height=128, *args, **kwargs):
self.thumb_width = thumb_width
self.thumb_height = thumb_height
super(ThumbnailImageField, self).__init__(*args, **kwargs)
def _get_path(self):
self._require_file()
return self.storage.path(self.name)
path = property(_get_path)
class ThumbnailImageFieldFile(ImageFieldFile):
def _get_thumb_path(self):
return _add_thumb(self.path)
thumb_path = property(_get_thumb_path)
def _get_thumb_url(self):
return _add_thumb(self.url)
thumb_url = property(_get_thumb_url)
def save(self, name, content, save=True):
super(ThumbnailImageFieldFile, self).save(name, content, save)
img = Image.open(self.path)
img.thumbnail(
(self.field.thumb_width, self.field.thumb_height),
Image.ANTIALIAS
)
img.save(self.thumb_path, 'JPEG')
def delete(self, save=True):
if os.path.exists(self.thumb_path):
os.remove(self.thumb_path)
super(ThumbnailImageFieldFile, self).delete(save)
attr_class = ThumbnailImageFieldFile
Code:
{% extends "base.html" %}
{% block title %}Item List{% endblock %}
{% block content %}
<p><a href="{% url index %}">« Back to main page</a></p>
<h2>Items</h2>
{% if object_list %}
<table>
<tr>
<th>Name</th>
<th>Sample Thumb</th>
<th>Description</th>
</tr>
{% for item in object_list %}
<tr>
<td><i>{{ item.name }}</i></td>
<td>
{% if item.photo_set.count %}
<a href="{{ item.get_absolute_url }}">
<img src="{{ item.photo_set.all.0.image.thumb_url }}" />
</a>
{% else %}
(No photos currently uploaded)
{% endif %}
</td>
<td>{{ item.description }}</td>
</tr>
{% endfor %}
</table>
{% else %}
<p>There are currently no items to display.</p>
{% endif %}
{% endblock %}