PythonとDjangoでAWS S3へファイルをアップロードする

よりインタラクティブなウェブサイトを構築するために、私たちはユーザーに情報を伝えるだけでなく、ユーザー自身がデータをアップロードできるようにしました。

これにより、ウェブサイトがエンドユーザーに提供できる機会が増え、より多くの方法が可能になります。

ユーザーがファイルをアップロードすることで、写真やビデオ、音楽を他のユーザーと共有したり、バックアップを取ったりすることができます。

また、ネイティブアプリをインストールする代わりに、Webサイトでファイルを管理したり、他の形式に変換したりする機能も提供できます。

ソーシャルメディアの世界的な普及は、ユーザーが画像や動画などのファイルをアップロードし、他のユーザーに見てもらったり、コミュニケーションの手段として利用されるようになったことに起因していると考えられます。

ユーザーがウェブサイトやプラットフォームにファイルをアップロードできるようになったことで、コミュニケーション手段が強化され、非常に多くの異なるフォーマットで情報を広めることができるようになりました。

この記事では、Django がどのようにファイルのアップロードを処理するのか、そして、どのように私たちのニーズに合わせてクラウドストレージを利用してこの機能を拡張できるのかを探ります。

Django がファイルストレージを処理する方法

Django は、概念を Web アプリケーションに変えるだけでなく、ファイルを扱える機能を提供し、ユーザが Web アプリケーションにファイルをアップロードして、さらに対話することを可能にします。

フォームを通して、ユーザはリクエストにファイルを添付することができ、そのファイルをアップロードしてバックエンドサーバに保存させることができます。

ファイルが保存される前に、そのファイルは一時的にどこかに保存され、その後処理されて最終的に意図した場所に保存されます。

例えば、アップロードされたファイルが2.5MB未満の場合、そのファイルの内容はメモリに保存され、処理中にすべてのオペレーションが完了するとディスクに書き込まれます。

このため、小さなファイルの場合は高速に処理されます。

2.5MB 以上のファイルでは、まずデータを受け取りながら一時的な場所に書き込まれ、処理が完了すると最終的な保存先に移動されます。

Django におけるファイルの動作は、 FILE_UPLOAD_MAX_MEMORY_SIZE のような様々な設定によってカスタマイズできます。

この設定によって、一時的な場所ではなくメモリに最初に書き込まれるファイルの 2.5MB のアップロード制限サイズを変更することができます。

また、 FILE_UPLOAD_PERMISSIONS により、アップロードされるファイルのデフォルトのパーミッションを設定することができます。

その他の設定は、 Django の公式ドキュメントのこのセクションに記載されています。

ファイルを保存する場所は?

Django を使った Web アプリケーションでは、アップロードされたファイルを様々な異なる場所に保存することができます。

Django のコードがデプロイされている私たち自身のサーバに保存することもできますし、保存のために他の場所に設置されたサーバに送信することもできます。

サーバのメンテナンスコストを削減し、パフォーマンスを向上させるために、アップロードされたファイルを私たちのサーバに保存しないことも可能です。

この場合、AWS、Azure、OneDriveなど、他のホステッド・ストレージ・プロバイダーにファイルを渡すことができる。

これまで述べてきたさまざまなサービスプロバイダが提供するAPIと対話するためのパッケージがいくつかあります。

それらは以下の通りです。

  • Django-Storages は、アップロードしたファイルを AWS Simple Storage Service (S3), Dropbox, OneDrive, Azure, Digital Ocean に保存することができます。
  • Django-S3-Storage は、Amazon S3 に直接ファイルをアップロードすることができます。
  • Django-Cumulus は、Rackspace と連携してストレージを使用することができます。
  • その他、Django-Dropbox、Django-Storage-Swift、Django-Cloudinary-Storage があります。その他はこちらで確認できます。

この記事では、Django-s3direct パッケージを使って、AWS の S3 にファイルを保存することにします。

私たちのアプリケーション – Django Drive

私たちは Django を使って、エンドユーザが閲覧するコンテンツをアップロードする Web アプリケーショ ンを構築する予定です。

これは、フレームワークに付属している Django の管理インターフェイスを使うことで実現されます。

私たちのサイトは、車を販売するために使われ、販売中の車の詳細を表示し、画像やビデオを追加する予定です。

販売中の車の画像や動画は、S3に保存される予定です。

今回は簡略化のため、ユーザー登録やログインは実装しません。

セットアップ

Pipenv を使って、Django アプリケーションを構築する孤立した環境を設定・管理します。

以下のコマンドを実行して、Python3 を使った環境を構築します。

$ pipenv install --three


環境のセットアップが完了したら、Django と Django-s3direct をインストールして、S3 へのファイルアップロードを処理できるようにします。

$ pipenv install django django-s3direct


Django は、アプリケーションのコア機能の実装を始める前に、プロジェクトをブートストラップ するためのコマンド群を提供します。

私たちの Django ドライブプロジェクトには、この記事の焦点となる単一のアプリケーショ ンがあります。

これを実現するために、以下のコマンドを実行します。

$ django-admin startproject django_drive && cd django_drive
$ django-admin startapp django_drive_app


django-admin startproject …コマンドはプロジェクトを作成し、django-admin startapp …` コマンドはアプリケーションを作成します。

最後に、migrateコマンドを実行して、データベースのテーブルを作成します。

$ python manage.py migrate


python manage.py runserver`コマンドを実行してプロジェクトを開始すると、次のページが表示され、セットアップが成功したことが確認できます。

AWS S3 にファイルをアップロードするため、デモ用にフリーティア AWS アカウントをセットアップする必要があります。

セットアップ後、S3 ダッシュボードに移動し、アップロードを格納する新しいバケットを作成できます。

Django-s3directが AWS のセットアップとやり取りするために、以下の認証情報AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_STORAGE_BUCKET_NAME` を提供する必要があります。

次に、django_drive/settings.py ファイルに以下の内容を追加します。

AWS_ACCESS_KEY_ID = 'aws-access-key-id'
AWS_SECRET_ACCESS_KEY = 'secret-access-key'
AWS_STORAGE_BUCKET_NAME = 'name-of-the-bucket'
AWS_S3_REGION_NAME = 'name-of-the-region'
AWS_S3_ENDPOINT_URL = 'https://s3.amazonaws.com'


S3DIRECT_DESTINATIONS = {
    'primary_destination': {
        'key': 'uploads/',
        'allowed': ['image/jpg', 'image/jpeg', 'image/png', 'video/mp4'],
    },
}


Django-s3direct` では、アップロード先を複数指定することができ、異なるファイルを別々の S3 バケットに転送することができます。

このプロジェクトでは、全てのアップロードを一つのバケットに入れることにします。

もう一つの便利な機能は、ウェブサイトにアップロードできるファイルの種類を制限できることである。

今回は、MP4動画、JPEG、PNG画像のみに限定しています。

Note: CORS や Access Setup など、Django-s3direct のセットアップに関する詳細は、こちらで確認することができます。

また、django_drive/urls.py ファイルに以下のエントリを追加する必要があります。

from django.urls import path, include


urlpatterns = [
    ...
    path('', include('django_drive_app.urls')),
    path('s3direct/', include('s3direct.urls')),
    ...
]


実装

まず、エンドユーザーに表示される車のデータモデルを作成します。

このモデルはまた、私たちのプラットフォームに車を追加するときに、管理者ダッシュボードに入力する情報を定義することになります。

車種は以下のようになります。

from django.db import models
from s3direct.fields import S3DirectField


class Car(models.Model):
    name = models.CharField(max_length=255, blank=False, null=False)
    year_of_manufacture = models.CharField(max_length=255, blank=False, null=False)
    price = models.CharField(max_length=255, blank=False, null=False)
    image = S3DirectField(dest='primary_destination', blank=True)
    video = S3DirectField(dest='primary_destination', blank=True)


def __str__(self):
        return f"{self.name} ({self.year_of_manufacture}) - {self.price}"


各車両には、名前、製造年、価格、画像または動画が保存されます。

モデルを作成した後、データベースにデータを格納するテーブルを作成するために、マイグレーションを実行しましょう。

$ python manage.py makemigrations
$ python manage.py migrate


Django admin dashboard を使ってプラットフォーム上の車を管理するので、 django_drive_app/admin.py にモデルを登録する必要があります。

from django.contrib import admin
from.models import Car


admin.site.register(Car)


次に、以下のコマンドを実行してプロンプトに従って、車の追加を担当するスーパーユーザを作成する必要があります。

$ python manage.py createsuperuser
$ python manage.py runserver


python manage.py runserver` コマンドは、単にアプリケーションを再起動するだけです。

サーバーを再起動した後、http://127.0.0.1:8000/admin の管理ダッシュボードに移動し、先ほど指定した認証情報でログインします。

サイト管理の下には、DJANGO_DRIVE_APPがあり、既存の車を追加・変更するオプションが表示されています。

車種を追加するためのフォームです。

車を保存すると、AWSコンソールにS3バケットにアップロードした画像が表示されます。

これは、ファイルがAWSにアップロードされたことを意味します。

では、車とそのデータをウェブサイトのエンドユーザーに表示し、各車に関連する画像や動画も表示するビューを作成します。

まず、django_drive_app/views.pyにビューを作成します。

from django.shortcuts import render
from django.views.generic import TemplateView
from .models import Car


class CarView(TemplateView):
    template_name = 'django_drive_app/cars.html'


def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['cars'] = Car.objects.all()
        return context


このビューでは、クラスベースの Django ビューを使用して、車を表示するための HTML ファイルをレンダリングします。

このビューでは、データベースに保存されている全ての車を取得するためにクエリを実行します。

次に、車を表示するために、 django_drive_app/templates/django_drive_app/cars.html を作成しましょう。

<!DOCTYPE html

<html
<head
<titleDjango Drive</title
</head
<body
<h3Welcome to Django Drive. </h3
<pHere are the current cars available for sale: </p
<div class="cars-container"
      {% for car in cars %}
        <div class="car"
<p
<b {{ car.name }} ({{ car.year_of_manufacture }}) </b <br/
            Price: {{ car.price }}
          </p
<!-- if the car has an image attached --
          {% if car.image %}
          <img height="200" src="{{ car.image }}" width="400"/
          {% endif %}
          <!-- If the car has a video --
          {% if car.video %}
            <video controls="" height="240" width="320"
<source src="{{ car.video }}" type="video/mp4"/
              Your browser does not support the video tag.
            </video
          {% endif %}
        </div
<hr/
      {% endfor %}
    </div
</body
</html


ビューとテンプレートを配置したら、エンドユーザーに車のリストを表示するためのエンドポイントを django_drive_app/urls.py に追加しましょう。

from django.conf.urls import url
from .views import CarView


urlpatterns = [
  url(r'^cars/$', CarView.as_view(), name="cars"),
]


ビューをインポートし、車をレンダリングするビューにエンドポイントをマッピングするURLエントリを追加します。

サーバーを再起動して、 127.0.0.1:8000/cars/ に移動すると、次のような画面が表示されます。

このように、画像や動画を添付した車を作成し、AWS の S3 サービスにアップロードしています。

同じ画像と動画がAWSから取得された後、Webアプリケーションでレンダリングされています。

結論

この記事では、管理者が Django 管理ダッシュボードを通じて AWS S3 にファイルをアップロードできるシンプルな Django アプリケーションを作成しました。

アップロードされたファイルは S3 にホストされているものとしてランディングページにレンダリングし、ユーザーが購入や閲覧を希望する車のビデオや画像も表示しました。

Django-s3direct` ライブラリを使用して、Django アプリケーションと、ファイルが保存されている AWS S3 の間のやり取りを処理しました。

Django の管理アプリケーションを通して、最終的にランディングページでエンドユーザーにレンダリングされるファイルをアップロードすることができました。

画像と動画の両方をアップロードし、レンダリングすることができました。

このプロジェクトのソースコードは、GitHubで公開されています。

タイトルとURLをコピーしました