Django的静态文件和AWS S3

Django静态文件和AWS S3 – Qiita
Django媒体文件和AWS S3 – Qiita

本次文章总结了在创建使用Django构建的博客“Django博客”(暂定名)时所进行的调查。虽然是第一次接触Django,但在大约3周的时间内完成了。尽管只是个α版本,但请注册用户后体验一下吧。
这是已部署在GAE上的“Django博客”。

本文将总结Django静态文件的使用以及部署到AWS S3的方式。

静态文件的分发在开发环境和生产环境中是不同的。在开发环境(DEBUG=True)中,使用Django的默认INSTALLED_APPS——django.contrib.staticfiles。而在生产环境中,我们将使用AWS S3。(通常情况下,可能更常见的是使用Nginx等而不是AWS S3。)

    • 開発環境(DEBUG=True):各アプリケーションのstaticディレクトリ(django.contrib.staticfiles)

 

    本番環境(DEBUG=False) :AWS S3 (django-storages)

管理静态文件(如图像、JavaScript、CSS等)- 官方文档
Django静态文件总结

1.创建测试项目

我会创建测试环境。

创建项目

首先创建Django项目。

python -m venv statictest
source statictest/bin/activate
cd statictest
pip freeze   # インストール済みは空であることを確認
pip install django  # Djangoをインストール
django-admin startproject statictest .

这是用于从远程访问的设置。

---
ALLOWED_HOSTS = ["www.mypress.jp"]
---

我会确认项目是否在此阶段正常运行。

python manage.py migrate
python manage.py runserver 0:8080

创建测试应用程序。

我将创建两个应用程序,一个名为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.开发环境 – 调试模式为真

在应用程序级别进行静态设置(开发环境)的方式是2-1。

如果 DEBUG=True ,则使用 django.contrib.staticfiles。在这种情况下,静态文件应该放在每个应用程序目录的 static 文件夹中。在运行 runserver 时,静态文件会自动从每个 static 文件夹中进行分发。

首先,在两个应用程序(test1、test2)下创建一个static和templates目录,然后在每个目录下再创建名为test1和test2的子目录。

mkdir -p ./test1/{static,templates}/test1
mkdir -p ./test2/{static,templates}/test2

就测试1应用程序而言,静态文件应该放置在test1/static/test1/下。通常情况下,我们需要根据需要创建css、js等目录。

由于本次讲解的是有关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
image.png
image.png

2-2.静态设定的共通部分

我们考虑在test1和test2中共同使用的静态文件。我们在项目目录的根目录下创建一个名为static的文件夹,并将共同的css文件放在其中。

mkdir -p ./static/css

设置STATICFILES_DIRS以使在上面创建的static目录生效。

---
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
image.png
image.png

将2-3.DEBUG=False 修改为 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的话,就不能使用django.contrib.staticfiles来分发静态文件。因为它存在安全和效率方面的问题,所以应该避免使用。这次我们决定将所有静态文件部署到AWS S3上,通过AWS S3进行分发。

创建 AWS IAM 和 S3

创建一个具有编程访问权限的IAM用户,并将其权限设置为AmazonS3FullAccess。其他设置按默认值创建,并记下Access Key ID和Secret Access Key。

我们将创建一个AWS S3存储桶,所有选项均为默认。为了向匿名用户公开静态文件,我们会添加以下类似的存储桶策略:”存储桶策略示例 – Amazon官方”。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AddPerm",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::static-test-reiwa/*"
        }
    ]
}

使用AWS S3进行静态分发的配置设定

要在Python中访问AWS,需要使用boto3。django-storages用于存储云存储、静态文件和上传的图像文件(媒体文件)。在这里,只展示了使用静态文件(css文件)的示例。有关上传图片等媒体文件的内容暂时不涉及,但与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',               # 追加
]

在settings.py中添加django-storages和AWS的配置。设置之前记下的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中。

image.png

完成以上的设定后,我将启动项目并尝试访问。我将在浏览器中进行访问。结果如我所愿。

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被设为亚马逊的链接。

<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>

这就是全部了。

bannerAds