Django媒体文件和AWS S3

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

这篇文章是关于使用Django创建的” Django Blog” (暂定名)进行的调查总结。虽然是我第一次使用Django,但在大约3个星期内完成了制作。虽然是α版,请注册用户进行尝试。这是已经部署到GAE上的版本。

本文将总结有关Django媒体文件处理以及上传至AWS S3的内容。

在Django中,我们将通过FileField和ImageField上传的文件称为媒体文件。

表格字段-公式文件

1.将文件上传到本地 – 开发环境(DEBUG=True)

创建一个测试项目

python -m venv localupload
source localupload/bin/activate
cd localupload/
pip freeze
pip install django
django-admin startproject localupload .

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

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

我将在此处确认项目是否正在运行。

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

1-2.上传至本地

我将创建一个用于将文件上传至本地的应用程序。

python manage.py startapp uploadapp
---
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'uploadapp',
]
---
---
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
---
    • MEDIA_URL : メディアファイル公開時のURLのプレフィクス。url=http://アプリのドメイン+MEDIA_URL+メディアファイル名

 

    MEDIA_ROOT : サーバから見たメディアルートの絶対パス. プロジェクトトップディレクトリ/media
from django.conf import settings
from django.contrib import admin
from django.urls import path, include
from django.conf.urls.static import static

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('uploadapp.urls')),
]
if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

在开发中(DEBUG=True)时,可以通过添加最后一个代码片段来保存图像到本地存储的MEDIA_ROOT,并且可以通过本地URL(MEDIA_URL)相对路径进行引用。但是在生产环境中(DEBUG=False),不推荐使用这种方法,应该像处理静态文件一样处理。

管理静态文件(如图像、JavaScript、CSS等)- 官方文档
Django静态文件与AWS S3- Qiita 的对接

from django.urls import path
from . import views

urlpatterns = [
    path('', views.Photo.as_view()),
]

嗯,這次我們使用的是ImageField而不是FileField。ImageField是這樣的一個東西。

    • ImageFieldは画像を扱うことに特化したFileFieldの派生フィールドです

 

    • ImageFieldにはPillowが必要。

 

    • 登録時のバリデーションで画像ファイルのチェックをする。画像ファイルでないもの、データの破損があるものは登録エラーとする(専用エラーメッセージあり)。

 

    管理用のフィールドを事前に用意すると、登録時に画像の高さと幅(pixel単位)を取得して保存する

现在我们来安装Pillow。

pip install Pillow

使用 ImageField 定义 models。

from django.db import models

class PhotoModel(models.Model):
    image = models.ImageField(upload_to='images')

    def __str__(self):
        return self.image.url

我将定义表单。

from django import forms
from .models import PhotoModel

class PhotoForm(forms.ModelForm):

    class Meta:
        model = PhotoModel
        fields = '__all__'

给出定义。

from django.views import generic
from .forms import PhotoForm
from .models import PhotoModel

class Photo(generic.CreateView):
    model = PhotoModel
    form_class = PhotoForm
    template_name = 'uploadapp/upload.html'
    success_url = '/'

    def get_context_data(self, **kwargs):
        context = super(Photo, self).get_context_data(**kwargs) # はじめに継承元のメソッドを呼び出す
        context["photos"] = PhotoModel.objects.all()
        return context

创建模板文件夹。

mkdir -p uploadapp/templates/uploadapp/

这是一个上传表单和已上传图片列表的显示。

    <form action="" method="POST" enctype="multipart/form-data">{% csrf_token %}        {{ form.as_p }}
        <button type="submit">アップロード</button>
    </form>

    {% for photo in photos %}
        <a href="{{ photo.image.url }}">{{ photo }}</a>
        <hr>
    {% endfor %}

我们开始启动项目

python manage.py runserver 0:8080

这是已经上传了两张图片的界面。

image.png

请根据 MEDIA_URL 的配置,查看以下的HTML源代码。图片的链接展示形式为 photo.image.url=”/media/images/tree5.jpg”。

    <form action="" method="POST" enctype="multipart/form-data"><input type="hidden" name="csrfmiddlewaretoken" value="m0qzyYvLhuUckbF5ctHAAJOCThqZ24Q7RE5c70EQ4bnTm05v3F33aYrn7br4jed2">
        <p><label for="id_image">Image:</label> <input type="file" name="image" accept="image/*" required id="id_image"></p>
        <button type="submit">アップロード</button>
    </form>


        <a href="/media/images/tree4jpeg.jpeg">/media/images/tree4jpeg.jpeg</a>
        <hr>

        <a href="/media/images/tree5.jpg">/media/images/tree5.jpg</a>
        <hr>

请确认设置了MEDIA_ROOT。 这是在项目顶级目录下运行tree命令的结果。

$ tree media/
media/
├── images
│   ├── tree4jpeg.jpeg
│   └── tree5.jpg
└── tree4jpeg.jpeg

2.将数据上传到远程 AWS S3 – 生产环境(DEBUG=False)

从这里开始,我们将查看将图像上传到AWS S3的设置。由于这是生产环境,我们将进行基本设置,将静态文件部署到AWS S3,并进行额外设置,将媒体文件上传到AWS S3。

请参考「Django static文件和AWS S3 – Qiita」以了解关于静态文件和AWS设置的信息。

首先是设定生产环境。

---
DEBUG = False
---

我将在AWS S3中创建一个新的存储桶,并为它添加以下策略。

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

请安装所需的库。

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',
    'uploadapp',
    'storages',      # 追加
]
---
# STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]

AWS_ACCESS_KEY_ID = 'AKIAXXXXXXXXXXXXXXXXXXXXX'
AWS_SECRET_ACCESS_KEY = 'YYYYYYYYYYYYYYYYYYYYYY'
AWS_STORAGE_BUCKET_NAME = 'media-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'


MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

DEFAULT_FILE_STORAGE = 'localupload.storage_backends.MediaStorage'

除了静态文件的配置之外,还添加了DEFAULT_FILE_STORAGE的配置。

静态资产和媒体资产的解释

    • static ファイルはSTATICFILES_STORAGE=S3Boto3Storageで設定。collectstaticが処理する。

 

    media ファイルはDEFAULT_FILE_STORAGEで設定。S3Boto3Storageを拡張し、’media’ディレクトリにアップロードするよう指定する。

扩展S3Boto3Storage是通过以下的storage_backends.py来进行的,该扩展会按照在DEFAULT_FILE_STORAGE中指定的方式操作。设置了当上传相同文件名的图片时,不会覆盖原有图片,而会自动重命名。

from storages.backends.s3boto3 import S3Boto3Storage

# 画像は同ファイル名での上書きを許さない
class MediaStorage(S3Boto3Storage):
    location = 'media'
    file_overwrite = False

创建一个”static”目录,并通过collectstatic将static文件部署到AWS S3。

mkdir static
python manage.py collectstatic

在这里,我们将从数据库表中删除之前上传的所有条目。
启动项目并上传两个图像文件。

python manage.py runserver 0:8080

你可以在以下画面中确认到这样的内容。

image.png

AWS S3的存储桶中有static和media目录。

image.png

媒体目录中确实上传了2个文件。

image.png

这次就这样吧。

广告
将在 10 秒后关闭
bannerAds