Djangoで画像やファイルをアップロードする方法

Djangoはやはり便利ですね。色々良しなにやってくれるから俺は結構気に入ってます。もちろんファイルの扱いも良しなにしてくれます。
今回はファイルアップロード出来るようにする方法についてお話しします。
DjangoではFileField や ImageFieldと言うのが提供されていて、これらを利用すると非常に簡単にアップロードファイルを取り扱うことができます。
FileField や ImageFieldを利用すると、DB上にはアップロードされたPathが入り、実ファイルは指定したサーバー上に保存されます。パフォマンス上、決してDBにファイルが入ることはありません。
では、とりあえずやってみましょう。

「settings.py」にMEDIA_ROOTとMEDIA_URLを設定

import os
ROOT_PATH = os.path.dirname(__file__) + '/..'
...
MEDIA_ROOT = ROOT_PATH + '/media/'
...
MEDIA_URL = '/media/'

MEDIA_ROOTはファイルが保存されるサーバー上のPathを指定します。
MEDIA_URLはファイルの公開URLを指定します。上記の例だとhttp://example.com/media/になります。

FileField や ImageFieldを使いModelを設定

...
upload = models.FileField(upload_to='uploads/')
...

FileFieldにはupload_to属性を指定します。
この例だとproject_root/media/uploads/のところにファイルが保存され、DBにはuploads/filenameとそのPathが保存されます。
DB上に該当するColumnを作成しておくことをお忘れなく!

urls.pyを設定

アップロードされたファイルが見られるように公開します。

...
from django.conf import settings
from django.conf.urls.static import static
...
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
...

これであなた自身のパソコンやテストサーバーでは正常にファイルが見れるはずです。

お疲れ様でした。

FAQ

上の通りにしても、テスト機では動くけど本番サーバーでは動かないよ?

上記の3ステップであなた自身のパソコンやテストサーバーでは正常にファイルが見れるはずです。
どういうことかと言うと、本番運用しているサーバーならApacheなどWebサーバーをかまして運用するのが普通だから、本番ではWebサーバーの設定も変えてあげないといけないと言うことです。
Apacheを例として取り上げると、下記のような設定を追加する必要があります。

...
Alias /media/ /project_root/media/
...

アップロードされたファイル名を変更して保存したい

会員のPKやIDなどを使ってファイル名付けて保存したい、もしくはセキュリティ問題などの理由でファイル名を変更して保存したい方結構いると思います。そんな方は下記のSnippetを使ってみてください。PKを利用して新たにファイル名を付けるものです。

    def path_and_rename(path, prefix, suffix):
        def wrapper(instance, filename):
            ext = filename.split('.')[-1]
            if instance.pk:
                filename = '{}{}{}.{}'.format(prefix, instance.pk, suffix, ext)
            else:
                filename = '{}.{}'.format(uuid4().hex, ext)
            return os.path.join(path, filename)
        return wrapper

使い方の例はこちら。

upload = models.FileField(upload_to=path_and_rename('uploads/', 'member-', '-doc'))

この例だとuploads/member-1234-doc.extと言うファイル名で保存されます。

公式文書のURL教えて!

https://docs.djangoproject.com/ja/3.0/faq/usage/#how-do-i-use-image-and-file-fields

django

Posted by YongJin Kim