Перейдите на вкладку «Пользователи» и нажмите кнопку «Добавить пользователя»:
Добавьте имя пользователя и выберите опцию программного доступа:
Нажмите Далее, чтобы перейти к разрешениям. На этом этапе нам нужно создать новую группу с правами доступа S3 и добавить в нее нового пользователя. Следуйте указаниям мастера и нажмите кнопку «Создать группу»:
Определите имя для группы и найдите встроенную политику AmazonS3FullAccess:
Нажмите в группе «Создать», чтобы завершить процесс создания группы, на следующем экране, недавно созданная группа будет отображаться выбранной, сохраните ее и, наконец, нажмите кнопку «Далее: обзор»:
Просмотрите информацию, если все правильно, перейдите к созданию нового пользователя. Далее вы должны увидеть эту информацию:
Запишите всю информацию: пользователь, идентификатор ключа доступа и секретный ключ доступа. Сохраните их на потом.
Нажмите на кнопку Закрыть, и давайте продолжим. Теперь пришло время создать нашу первую «корзину».
Корзина (bucket) — это то, что мы называем контейнером хранения в S3. Мы можем работать с несколькими сегментами в рамках одного проекта Django. Но, по большей части, вам понадобится только одна корзина на сайт.
Нажмите в меню «Сервисы» и найдите S3. Он расположен под хранилищем. Если вы видите экран ниже, вы находитесь в правильном месте.
Нажмите на + Создать корзину, чтобы начать поток. Установите DNS-совместимое имя для вашей корзины. Оно будет использоваться для идентификации ваших активов. В моем случае я выбираю sibtc-static. Таким образом, путь к моим ресурсам будет примерно таким: https://sibtc-static.s3.amazonaws.com/static/.
Оставьте оставшиеся настройки без изменений, перейдите к следующим шагам, просто используя значения по умолчанию, и, наконец, нажмите кнопку «Создать корзину». Далее вы должны увидеть экран ниже:
Давайте оставим это так и начнем работать на стороне Джанго.
Установка
Самый простой способ - установить библиотеки с помощью pip
:
pip install boto3
pip install django-storages
Теперь добавьте storages
к вашему INSTALLED_APPS
внутри модуля settings.py
:
settings.py
INSTALLED_APPS = [
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'storages',
]
Работа только со статическими активами
Это простейший вариант использования. Он работает "из коробки" с минимальной конфигурацией. Вся конфигурация ниже идет внутри модуля settings.py
:
settings.py
AWS_ACCESS_KEY_ID = 'AKIAIT2Z5TDYPX3ARJBA'
AWS_SECRET_ACCESS_KEY = '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'
AWS_STORAGE_BUCKET_NAME = 'sibtc-static'
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
AWS_S3_OBJECT_PARAMETERS = {
'CacheControl': 'max-age=86400',
}
AWS_LOCATION = 'static'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'mysite/static'),
]
STATIC_URL = 'https://%s/%s/' % (AWS_S3_CUSTOM_DOMAIN, AWS_LOCATION)
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
Обратите внимание, что у нас есть конфиденциальная информация, такая как AWS_ACCESS_KEY_ID
и AWS_SECRET_ACCESS_KEY
. Не следует помещать его непосредственно в файл settings.py
или фиксировать в общедоступном хранилище. Вместо этого используйте переменные окружения или используйте библиотеку Python Decouple.
Чтобы проиллюстрировать этот пример использования, я создал минимальный проект Django:
mysite/
|-- mysite/
| |-- static/
| | |-- css/
| | | +-- app.css
| | +-- img/
| | +-- thumbs-up.png
| |-- templates/
| | +-- home.html
| |-- __init__.py
| |-- settings.py
| |-- urls.py
| +-- wsgi.py
+-- manage.py
Как видите, обработка статических файлов должна проходить без проблем:
home.html
{% load static %}<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>S3 Example Static Only</title>
<link rel="stylesheet" type="text/css" href="{% static 'css/app.css' %}">
</head>
<body>
<header>
<h1>S3 Example Static Only</h1>
</header>
<main>
<img src="{% static 'img/thumbs-up.png' %}">
<h2>It's working!</h2>
</main>
<footer>
<a href="https://simpleisbetterthancomplex.com">www.SimpleIsBetterThanComplex.com</a>
</footer>
</body>
</html>
Даже если мы используем нашу локальную машину, нам нужно будет выполнить команду collectstatic
, так как наш код будет ссылаться на удаленное местоположение:
python manage.py collectstatic
Вы заметите, что процесс копирования займет больше времени, чем обычно. Это ожидаемо. Я удалил Django Admin из INSTALLED_APPS
, чтобы пример стал чище. Но если вы попробуете это локально, вы увидите множество файлов, скопированных в вашу корзину S3.
Если мы проверим на веб-сайте AWS, мы увидим наши статические активы там:
И наконец, результат:
Как видите, серверная часть хранилища старается перевести тег шаблона {% static 'img / thumbs-up.png'%}
в https://sibtc-static.s3.amazonaws.com/static/img/thumbs- up.png и загрузить его из корзины S3.
В следующем примере вы узнаете, как работать со статическими и медиа-активами.
Работа со статическими и медиаресурсами
Для этого примера я создал новую корзину с именем sibtc-assets.
Конфигурация settings.py
будет очень похожа. За исключением того, что мы расширим storages.backends.s3boto3.S3Boto3Storage
, добавив несколько пользовательских параметров, чтобы иметь возможность хранить загруженные пользователем файлы, то есть медиаресурсы, в другом месте, а также указывать S3 не переопределять файлы с помощью одно и то же имя
Обычно мне нравится создавать файл storage_backends.py
в том же каталоге, что и мой settings.py
, и вы можете определить новый бэкэнд хранилища следующим образом:
storage_backends.py
from storages.backends.s3boto3 import S3Boto3Storage
class MediaStorage(S3Boto3Storage):
location = 'media'
file_overwrite = False
Теперь в файле settings.py
нам нужен новый бэкэнд для опции DEFAULT_FILE_STORAGE
:
settings.py
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'mysite/static'),
]
AWS_ACCESS_KEY_ID = 'AKIAIT2Z5TDYPX3ARJBA'
AWS_SECRET_ACCESS_KEY = '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'
AWS_STORAGE_BUCKET_NAME = 'sibtc-assets'
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
AWS_S3_OBJECT_PARAMETERS = {
'CacheControl': 'max-age=86400',
}
AWS_LOCATION = 'static'
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
STATIC_URL = "https://%s/%s/" % (AWS_S3_CUSTOM_DOMAIN, AWS_LOCATION)
DEFAULT_FILE_STORAGE = 'mysite.storage_backends.MediaStorage' # <-- here is where we reference it
Для иллюстрации загрузки файла я создал приложение с именем core
и определил следующую модель:
models.py
from django.db import models
class Document(models.Model):
uploaded_at = models.DateTimeField(auto_now_add=True)
upload = models.FileField()
Тогда вот как выглядит моё представление:
views.py
from django.contrib.auth.decorators import login_required
from django.views.generic.edit import CreateView
from django.urls import reverse_lazy
from .models import Document
class DocumentCreateView(CreateView):
model = Document
fields = ['upload', ]
success_url = reverse_lazy('home')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
documents = Document.objects.all()
context['documents'] = documents
return context
Шаблон document_form.html:
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
<table>
<thead>
<tr>
<th>Name</th>
<th>Uploaded at</th>
<th>Size</th>
</tr>
</thead>
<tbody>
{% for document in documents %}
<tr>
<td><a href="{{ document.upload.url }}" target="_blank">{{ document.upload.name }}</a></td>
<td>{{ document.uploaded_at }}</td>
<td>{{ document.upload.size|filesizeformat }}</td>
</tr>
{% empty %}
<tr>
<td colspan="3">No data.</td>
</tr>
{% endfor %}
</tbody>
</table>
Как вы можете видеть, я использую только встроенные ресурсы Django в шаблоне. Вот как выглядит этот шаблон:
Я не буду вдаваться в подробности о загрузке файлов, вы можете прочитать подробное руководство здесь в блоге (см. соответствующие ссылки в конце этой статьи для получения дополнительной информации).
Теперь тестируем загруженные пользователем файлы:
Я создал свой шаблон, чтобы вывести список загруженных файлов, поэтому после того, как пользователь загрузит какое-либо изображение или документ, оно будет отображаться, как на картинке выше.
Затем, если мы нажмем на ссылку, которая является обычной {{ document.upload.url }}
, управляемой Django, она отобразит изображение из корзины S3:
Теперь, если мы проверим нашу корзину, то увидим, что есть статический и медиа каталог:
Смешивание публичных активов и частных активов
Используя почти те же понятия, вы определяете некоторые ресурсы, которые будут храниться в хранилище S3 в частном порядке. Смотрите конфигурацию ниже:
storage_backends.py
from django.conf import settings
from storages.backends.s3boto3 import S3Boto3Storage
class StaticStorage(S3Boto3Storage):
location = settings.AWS_STATIC_LOCATION
class PublicMediaStorage(S3Boto3Storage):
location = settings.AWS_PUBLIC_MEDIA_LOCATION
file_overwrite = False
class PrivateMediaStorage(S3Boto3Storage):
location = settings.AWS_PRIVATE_MEDIA_LOCATION
default_acl = 'private'
file_overwrite = False
custom_domain = False
settings.py
AWS_ACCESS_KEY_ID = 'AKIAIT2Z5TDYPX3ARJBA'
AWS_SECRET_ACCESS_KEY = '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'
AWS_STORAGE_BUCKET_NAME = 'sibtc-assets'
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
AWS_S3_OBJECT_PARAMETERS = {
'CacheControl': 'max-age=86400',
}
AWS_STATIC_LOCATION = 'static'
STATICFILES_STORAGE = 'mysite.storage_backends.StaticStorage'
STATIC_URL = "https://%s/%s/" % (AWS_S3_CUSTOM_DOMAIN, AWS_STATIC_LOCATION)
AWS_PUBLIC_MEDIA_LOCATION = 'media/public'
DEFAULT_FILE_STORAGE = 'mysite.storage_backends.PublicMediaStorage'
AWS_PRIVATE_MEDIA_LOCATION = 'media/private'
PRIVATE_FILE_STORAGE = 'mysite.storage_backends.PrivateMediaStorage'
Затем мы можем определить этот новый PrivateMediaStorage
непосредственно в модели:
models.py
from django.db import models
from django.conf import settings
from django.contrib.auth.models import User
from mysite.storage_backends import PrivateMediaStorage
class Document(models.Model):
uploaded_at = models.DateTimeField(auto_now_add=True)
upload = models.FileField()
class PrivateDocument(models.Model):
uploaded_at = models.DateTimeField(auto_now_add=True)
upload = models.FileField(storage=PrivateMediaStorage())
user = models.ForeignKey(User, related_name='documents')
После загрузки личного файла, если вы попытаетесь получить URL-адрес содержимого, API сгенерирует длинный URL-адрес, срок действия которого истекает через несколько минут.:
Если вы попытаетесь получить к нему доступ напрямую, без параметров, вы получите сообщение об ошибке от AWS:
Выводы
Я надеюсь, что это руководство помогло прояснить некоторые концепции Amazon S3 и помогло вам, по крайней мере, начать работу. Не бойтесь копаться в официальной документации как из boto3, так и из библиотеки django-storages.