Sunday, September 23, 2007

django で サムネイル付き画像をアップロードする方法(2) アップロードする方法2(modelを使う)

前回のサムネイル画像のアップロードの書き込み
http://programing-a2c-jp.blogspot.com/2007/09/django.html
ではviewの側にサムネイル画像の保存処理を書いていたがadminから画像を保存するときにサムネイルを自ら指定しないと保存できないといった問題があったのでmodelのsaveメソッドを再定義してサムネイル保存の処理を追加してみた。これでadmin側から画像を保存する時もサムネイルが自動生成されるようになった。

####### models.py class PhotoWithThumb ######
class PhotoWithThumb (models.Model):
photo_name = models.CharField(maxlength=200)
pub_date = models.DateTimeField('date published')
image = models.ImageField(upload_to='./', blank=False, null=True)
thumb = models.ImageField(upload_to='./', blank=True, null=True)

class Admin:
list_display = ('photo_name', 'pub_date', 'image', 'thumb')

def save(self):
thumbsize = settings.THUMBNAIL_FRAME_SIZE

# create file name and etc...
filename = os.path.join(settings.MEDIA_ROOT, self.get_image_filename())
filename = filename.encode()
try:
thumb_im = Image.open(filename)
except IOError:
# can't open original file...
sys.stderr.write("can't open original image to create thumbnail file\n")
raise IOError

#thumb_im = thumb_im.resize(thumbsize)
thumb_im = image_util.image_resize_keep_aspect( thumb_im, thumbsize )

body,ext = os.path.splitext( os.path.basename(filename) )
filename = body + "_thumb" + ".jpg"

# If the filename already exists, keep adding an underscore to the name of
# the file until the filename doesn't exist.
# took from django/build/lib/django/db/models/base.py
while os.path.exists(filename):
try:
dot_index = filename.rindex('.')
except ValueError: # filename has no dot
filename += '_'
else:
filename = filename[:dot_index] + '_' + filename[dot_index:]

thumb_im.save(os.path.join(settings.MEDIA_ROOT, filename), "JPEG")

# saveメソッドの中ではオブジェクトの __repr__ しか見ていないので次の書き方でよい。
self.thumb = filename

#以下のように書いてもよい。
"""
class Thumb:
def __init__(self, filename):
self.filename = filename
def __repr__(self):
return self.filename

self.thumb = Thumb(filename)
setattr(self.thumb, "filename", filename)
"""
models.Model.save(self)
###############################################################

view 側では PhotoWithThumb の photo_name と image, のフィールドに値を設定した後 save_image_fileメソッド を呼ぶ

############### views.py ############
def upload_photo_prompt(request):
"""
upload file and save with thumbnail file

thumbnail file name create as forrow ( original file name is 'orgfile.jpg')
'orgfile_thumb.jpg'

"""
thumbsize = settings.THUMBNAIL_FRAME_SIZE
t = loader.get_template('photos/upload_photo.html')

if request.method == 'POST':
# get cleaned PhotoWithThumbForm
form = PhotoWithThumbForm(request.POST, request.FILES)

if form.is_valid():
form.full_clean()
cleaned_data = form.cleaned_data

# get cleaned datetime
df = forms.DateTimeField()
cleaned_datetime = df.clean(datetime.datetime.now())

# stuff and save PhotoWithThumb
p = PhotoWithThumb()
p.photo_name = cleaned_data['photo_name']
p.image = cleaned_data['image']
p.pub_date = cleaned_datetime

p.save_image_file(cleaned_data['image'].filename, cleaned_data['image'].content)

return HttpResponseRedirect('../upload_photo_done/')
else:
form = PhotoWithThumbForm()

# display upload form
c = Context({ 'form' : form })
return HttpResponse(t.render(c))

########### image_util.py ##############
def image_resize_keep_aspect ( im, frame_size ):
"""
image resize but keep original aspect
@param im : source image
@param frame_size : maximam rectangle of image
"""

size = [0,0]
im_aspect = im.size[0] / float( im.size[1] )
frame_aspect = frame_size[0] / float( frame_size[1] )

if im_aspect > frame_aspect:
# fit image to frame width
size[0] = int( frame_size[0] )
size[1] = int( size[0] / im_aspect )
else:
# fit image to frame height
size[1] = int( frame_size[1] )
size[0] = int( size[1] * im_aspect )

return im.resize( size )

0 Comments:

Post a Comment

<< Home