Tuesday, September 18, 2007

django で サムネイル付き画像を
アップロードする方法

djangoのsvn版(2007-09-16)のnewformsを使ってview側で主に処理を行うことでサムネイル付き画像のアップロードに挑戦してみた。
ファイルの保存を行うときはsaveメソッドでなくsave_FIELD_fileメソッド(FIELDには ファイルインスタンスのフィールド名が入る)を使うとかが、注意点かもしれない。

参考にしたのは
http://www.oluyede.org/blog/2007/03/18/django-image-uploading-validation-and-newforms/
など。
でも上記のサイトのコードにある

       
new_data = request.POST.copy()
new_data.update(request.FILES)
などはうまくいかなかったので含めなかった。
また、0.96 には無いnewformsのImageField()を使っている。

########### models.py ##########
from django.db import models
from django.db.models import fields
from django import newforms as forms

from django.utils.translation import gettext as _
# サムネイル画像データも扱うクラス'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')
#ユーザからの入力を扱うクラス'PhotoWithThumbForm'
class PhotoWithThumbForm(forms.Form):
photo_name = forms.CharField(max_length=200, required=True, label=_('Photo Name'))
image = forms.ImageField(widget=forms.FileInput, required=True, label=_('Photo') )

########## views.py ############
# サムネイルを生成し、保存する処理の中心
from django.template import Context, loader
from django.shortcuts import render_to_response, get_object_or_404
from django.http import HttpResponse
from django.http import HttpResponseRedirect
from django import newforms as forms
from django.db.models import fields

import datetime
import Image
from StringIO import StringIO
from os import path

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 = (255,255)
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())

# get cleaned thumbnail data
thumb_file = StringIO()

thumb_fname = cleaned_data['image'].filename
body,ext = path.splitext(path.basename(thumb_fname))
thumb_fname = body + "_thumb" + ".jpg"

im = Image.open(StringIO(cleaned_data['image'].content))
im = im.resize(thumbsize)
im.save(thumb_file, "JPEG")

thumb_data = { 'filename' : thumb_fname, 'content' : thumb_file.getvalue() }
thumb_field = forms.ImageField()
cleaned_thumb = thumb_field.clean(thumb_data)

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

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

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

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

########## upload_photo.html ################
{% extends "plane.html" %}

{% block title %} Upload image {% endblock %}

{% block body_content %}
<h1> Upload image </h1>
<form method="post" enctype="multipart/form-data">
<table>
{{ form }}
</table>
<input type="submit" value="upload photo"/>
</FORM>
{% endblock %}


######### upload_photo_done.html #########
{% extends "plane.html" %}

{% block title %} Upload image {% endblock %}

{% block body_content %}
<h1> image is uploaded </h1>
{% endblock %}


########## plane.html #########
<!DO
CTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<HTML xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

<HEAD>
<TITLE>{% block title %} Plane html page {% endblock %}</TITLE>
</HEAD>
<BODY>
{% block body_content %} {% endblock %}
</BODY>
</HTML>

以上のような形でサムネイル画像を自動で保存できるようになったが、views.pl の側で処理を行っていると admin で写真をアップロードした場合に自動でサムネイル画像を生成&保存してくれないなど問題も多いので今後modelのsave_FIELD_fileメソッドをオーバーライドすることでサムネイルの保存もできるようにしたい。

1 Comments:

Blogger a2c_s_1980 said...

models.py に
インポートするモジュール
class PhotoWithThumbForm(forms.Form)
を追記
class PhotoWithThumb
のフィールドを
fields.ImageField
から
models.ImageField
に修正

8:49 AM  

Post a Comment

<< Home