Django staticファイルとAWS S3 - Qiita
Django mediaファイルとAWS S3 - Qiita
※今回の記事はDjangoを利用したブログである「Djangoブログ」(仮称)作成時に調査したことをまとめたものです。Djangoは初めてでしたが3週間程度で作りました。α版ですが、どうぞユーザ登録して使ってみてください。
「Djangブログ」 - GAEにDeployしたものです
本記事ではDjangoのstaticファイルの扱いと、AWS S3へのdeployについてまとめます。
staticファイルの配信は、開発環境と本番環境では異なります。開発環境(DEBUG=True)ではDjangoのデフォルトのINSTALLED_APPSであるdjango.contrib.staticfilesを使います。本番環境では、今回はAWS S3を使います。(通常は、AWS S3を使うよりはNginxとかを使う場合が多いかもです。)
- 開発環境(DEBUG=True):各アプリケーションのstaticディレクトリ(django.contrib.staticfiles)
- 本番環境(DEBUG=False) :AWS S3 (django-storages)
静的ファイル (画像、JavaScript、CSS など) を管理する - 公式ドキュメント
Django staticファイル まとめ
#1.テストプロジェクト作成
テスト環境を作ります。
##1-1.プロジェクト作成
まずはDjangoのプロジェクトを作成します。
python -m venv statictest
source statictest/bin/activate
cd statictest
pip freeze # インストール済みは空であることを確認
pip install django # Djangoをインストール
django-admin startproject statictest .
Remoteからアクセスするための設定です。
---
ALLOWED_HOSTS = ["www.mypress.jp"]
---
ここまででプロジェクトが動作するので確認します。
python manage.py migrate
python manage.py runserver 0:8080
##1-2.テストアプリ作成
test1とtest2というアプリケーションを作成します。
python manage.py startapp test1
python manage.py startapp test2
アプリを追加します。
---
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'test1.apps.Test1Config', # 追加
'test2.apps.Test2Config', # 追加
]
---
URLパスを追加します。
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('test1/', include('test1.urls')),
path('test2/', include('test2.urls')),
]
from django.urls import path
from django.views.generic import TemplateView
urlpatterns = [
path('', TemplateView.as_view(template_name="index.html")),
]
from django.urls import path
from django.views.generic import TemplateView
urlpatterns = [
path('', TemplateView.as_view(template_name="index.html")),
]
#2. 開発環境 - DEBUG=True
##2-1.アプリ単位でのstatic設定(開発環境)
DEBUG=Trueでdjango.contrib.staticfilesを使います。この場合、staticファイルは、各アプリケーションディレクトリ直下のstaticディレクトリに置くことになります。 staticファイルは、runserver実行時に自動的に各staticディレクトリから配信されます。
まず2つのアプリケーション(test1,test2)の下に、staticとtemplatesディレクトリを作成し、さらにそれぞれの下にtest1、とtest2というディレクトリを作成します。
mkdir -p ./test1/{static,templates}/test1
mkdir -p ./test2/{static,templates}/test2
test1アプリケーションに関して言えば、staticファイルはtest1/static/test1/の下に置きます。普通は、必要に応じてさらにcss、js、等のディレクトリを作成します。
今回はstaticファイルはcssに関して説明するので、以下のようにサブディレクトリを作成します。
mkdir ./test1/static/test1/css
mkdir ./test2/static/test2/css
{% load static %}
<html>
<head>
<title>Django blog</title>
<link rel="stylesheet" href="{% static 'test1/css/base.css' %}">
</head>
<body>
<header>
<h1>test1</h1>
</header>
<div>
test page!
</div>
</body>
</html>
{% load static %}
<html>
<head>
<title>Django blog</title>
<link rel="stylesheet" href="{% static 'test2/css/base.css' %}">
</head>
<body>
<header>
<h1>test1</h1>
</header>
<div>
test page!
</div>
</body>
</html>
h1 {
color: red;
}
h1 {
color: blue;
}
以上の設定を行ったら、プロジェクトを起動してアクセスしてみます。ブラウザでアクセスしてみます。思い通りの結果です。
python manage.py runserver 0:8080
##2-2.共通のstatic設定
test1とtest2で共通に使うstaticファイルを考えます。プロジェクトディレクトリ直下にstaticディレクトリをつくり、そこに共通のcssファイルを置くことにします。
mkdir -p ./static/css
上で作ったstaticディレクトリが有効になるようにSTATICFILES_DIRSを設定します。
---
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')] # 追加
以下のような共通のbase.cssを定義します。前とはディレクトリ名が違うことに注意してください。
div {
color: green;
}
テンプレートで、追加したbase.cssを参照するようにします。test1とtest2の両方を変更します。
{% load static %}
<html>
<head>
<title>Static test1</title>
<link rel="stylesheet" href="{% static 'test1/css/base.css' %}">
<link rel="stylesheet" href="{% static 'css/base.css' %}">
</head>
<body>
<header>
<h1>test1</h1>
</header>
<div>
test page!
</div>
</body>
</html>
以上の設定を行ったら、プロジェクトを起動してアクセスしてみます。ブラウザでアクセスしてみます。思い通りの結果です。「test page!」が緑色になっています。
python manage.py runserver 0:8080
##2-3.DEBUG=False にしてみる
ここまでの実験はstatictest/settings.pyのDEBUGをTrueにした場合の結果です。DEBUGをFalseにするとstaticファイル(base.css)が一つも読み込まれなくなります。django.contrib.staticfilesがstaticファイルの配信を止めてしまうからです。それでは本番環境(Debug=False)ではどうするかが以下の記事になります。
#3.本番環境(AWS S3)- DEBUG=False
DEBUG=Falseの場合には、staticファイルの配信にはdjango.contrib.staticfilesを使うことができません。セキュリティや効率の問題があるので避けるべきだとガイドされています。今回はAWS S3へ全てのstaticファイルをDeployすることで、AWS S3に配信させることにします。
##3-1.AWS IAMとS3の作成
programmatic accessのIAMユーザを作成し、グループの権限にAmazonS3FullAccessを指定します。その他はデフォルトで作成し、Access key ID と Secret access keyをメモっておきます。
AWS S3のバケットを作ります。オプションは全てデフォルト。staticファイルは匿名ユーザに公開しますので、以下のようなバケットポリシーを付与します。「バケットポリシーの例 - Amazon公式」
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AddPerm",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::static-test-reiwa/*"
}
]
}
##3-2.static配信にAWS S3を利用するための設定
PythonからAWSへアクセスするためにはboto3を使用します。django-storagesはクラウドストレージを、staticファイルやアップロード画像ファイル(mediaファイル)の保存に使うためのものです。ここではstaticファイル(cssファイル)のみの使用例を示します。画像のアップロードなどmediaファイルについては割愛させていただきますが、markdownXなどと併用したときはとても便利に使えます。いずれdjango-storages + markdownXに関する記事を掲載できればと思いますが、今回は触れません。
pip install boto3
pip install django-storages
アプリケーションを追加します。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'test1.apps.Test1Config',
'test2.apps.Test2Config',
'storages', # 追加
]
さらにdjango-storagesとAWSの設定をsettings.pyに追加します。先ほどメモしたAccess key ID と Secret access keyやバケット名などを設定します。
# STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
AWS_ACCESS_KEY_ID = 'AKIAXXXXXXXXXXXXXX'
AWS_SECRET_ACCESS_KEY = 'YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY'
AWS_STORAGE_BUCKET_NAME = 'static-test-reiwa'
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
AWS_S3_OBJECT_PARAMETERS = {
'CacheControl': 'max-age=86400',
}
AWS_LOCATION = 'static'
AWS_DEFAULT_ACL = None
STATIC_URL = 'https://%s/%s/' % (AWS_S3_CUSTOM_DOMAIN, AWS_LOCATION)
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
以上の設定をした後に、以下のコマンドを発行します。
python manage.py collectstatic
このコマンドで以下のようにAWS S3に全てのstaticファイルがdeployされます。
以上の設定を行ったら、プロジェクトを起動してアクセスしてみます。ブラウザでアクセスしてみます。思い通りの結果です。
python manage.py runserver 0:8080
index.htmlを確認してみます。
レンダー前のテンプレートは以下のようなものでした。
{% load static %}
<html>
<head>
<title>Static test1</title>
<link rel="stylesheet" href="{% static 'test1/css/base.css' %}">
<link rel="stylesheet" href="{% static 'css/base.css' %}">
</head>
<body>
<header>
<h1>test1</h1>
</header>
<div>
test page!
</div>
</body>
</html>
レンダー後にブラウザに表示されたHtmlは以下のようになります。base.cssのurlがamazonのものになっていることに注意してください。
<html>
<head>
<title>Static test1</title>
<link rel="stylesheet" href="https://static-test-reiwa.s3.amazonaws.com/static/test1/css/base.css">
<link rel="stylesheet" href="https://static-test-reiwa.s3.amazonaws.com/static/css/base.css">
</head>
<body>
<header>
<h1>test1</h1>
</header>
<div>
test page!
</div>
</body>
</html>
今回は以上です。