読者です 読者をやめる 読者になる 読者になる

FileFieldにはまった

Django

FileFieldなんて久しく使っていなかったし、そもそもWebフォーム経由でファイルをアップロードするコードなんて久しく書いていなかったので、DjangoでFileFieldを使おうとして少々はまった。

newformsが導入された当初は、Formの第一引数にrequest.FILESを渡す使い方だったような気がして、ずっと次のように書いていたのだが、

# -*- coding: utf-8 -*-
import django.newforms as forms
from django.shortcuts import *

class AttachmentForm(forms):
    attachment = forms.FileField()

def upload(req):
    """
    間違い!
    """
   form = AttachmentForm(req.FILES)
   if form.is_valid():
        data = form.clean()
        #ここで何かする

    return render_to_response('form.html', {'form':form})

正しくはドキュメントにある通り、第二引数にrequest.FILESを渡す。

class AttachmentForm(forms):
    attachment = forms.FileField()

def upload(req):
   form = AttachmentForm(req.POST or None, req.FILES)
   if form.is_valid():
        attachment = form.clean()['attachment']
        #ここで何かする

    return render_to_response('form.html', {'form':form})

form.clean()をしたときに返ってくるのが、いつの間にかUploadedFileというラッパーオブジェクトになっていた。前は辞書型が返ってきたような気がするが、これは気が利いているデザインだと思う。

class UploadedFile(StrAndUnicode):
    "A wrapper for files uploaded in a FileField"
    def __init__(self, filename, content):
        self.filename = filename
        self.content = content

    def __unicode__(self):
        """
        The unicode representation is the filename, so that the pre-database-insertion
        logic can use UploadedFile objects
        """
        return self.filename