copy files from fixtures dir to MEDIA_ROOT (or remote storage) during load_initial_data (#255)
Note: This change will require any existing deployments to manually copy bakerydemo/base/fixtures/media/original_images/ into bakerydemo/media/pull/262/head
|
@ -9,7 +9,6 @@
|
||||||
/data
|
/data
|
||||||
.~*
|
.~*
|
||||||
common/CACHE
|
common/CACHE
|
||||||
bakerydemo/media/images/*
|
|
||||||
bakerydemo/settings/local.py
|
bakerydemo/settings/local.py
|
||||||
bakerydemodb
|
bakerydemodb
|
||||||
__pycache__
|
__pycache__
|
||||||
|
|
|
@ -22,6 +22,9 @@ script:
|
||||||
- docker-compose run app /bin/sh -c "/venv/bin/pip install flake8 && /venv/bin/flake8 ."
|
- docker-compose run app /bin/sh -c "/venv/bin/pip install flake8 && /venv/bin/flake8 ."
|
||||||
- docker-compose run app /venv/bin/python /code/manage.py check
|
- docker-compose run app /venv/bin/python /code/manage.py check
|
||||||
- docker-compose run app /venv/bin/python /code/manage.py makemigrations --check
|
- docker-compose run app /venv/bin/python /code/manage.py makemigrations --check
|
||||||
|
- docker-compose run app /venv/bin/python /code/manage.py load_initial_data
|
||||||
|
# Check for broken image links (wget will have a non-zero exit code if it encounters a 404)
|
||||||
|
- wget -m http://localhost:8000
|
||||||
|
|
||||||
after_script:
|
after_script:
|
||||||
- docker-compose logs
|
- docker-compose logs
|
||||||
|
|
Przed Szerokość: | Wysokość: | Rozmiar: 221 KiB Po Szerokość: | Wysokość: | Rozmiar: 221 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 71 KiB Po Szerokość: | Wysokość: | Rozmiar: 71 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 78 KiB Po Szerokość: | Wysokość: | Rozmiar: 78 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 56 KiB Po Szerokość: | Wysokość: | Rozmiar: 56 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 102 KiB Po Szerokość: | Wysokość: | Rozmiar: 102 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 40 KiB Po Szerokość: | Wysokość: | Rozmiar: 40 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 134 KiB Po Szerokość: | Wysokość: | Rozmiar: 134 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 110 KiB Po Szerokość: | Wysokość: | Rozmiar: 110 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 59 KiB Po Szerokość: | Wysokość: | Rozmiar: 59 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 398 KiB Po Szerokość: | Wysokość: | Rozmiar: 398 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 148 KiB Po Szerokość: | Wysokość: | Rozmiar: 148 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 189 KiB Po Szerokość: | Wysokość: | Rozmiar: 189 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 102 KiB Po Szerokość: | Wysokość: | Rozmiar: 102 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 164 KiB Po Szerokość: | Wysokość: | Rozmiar: 164 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 12 KiB Po Szerokość: | Wysokość: | Rozmiar: 12 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 360 KiB Po Szerokość: | Wysokość: | Rozmiar: 360 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 134 KiB Po Szerokość: | Wysokość: | Rozmiar: 134 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 208 KiB Po Szerokość: | Wysokość: | Rozmiar: 208 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 164 KiB Po Szerokość: | Wysokość: | Rozmiar: 164 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 85 KiB Po Szerokość: | Wysokość: | Rozmiar: 85 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 114 KiB Po Szerokość: | Wysokość: | Rozmiar: 114 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 124 KiB Po Szerokość: | Wysokość: | Rozmiar: 124 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 241 KiB Po Szerokość: | Wysokość: | Rozmiar: 241 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 170 KiB Po Szerokość: | Wysokość: | Rozmiar: 170 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 494 KiB Po Szerokość: | Wysokość: | Rozmiar: 494 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 163 KiB Po Szerokość: | Wysokość: | Rozmiar: 163 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 171 KiB Po Szerokość: | Wysokość: | Rozmiar: 171 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 272 KiB Po Szerokość: | Wysokość: | Rozmiar: 272 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 45 KiB Po Szerokość: | Wysokość: | Rozmiar: 45 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 18 KiB Po Szerokość: | Wysokość: | Rozmiar: 18 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 185 KiB Po Szerokość: | Wysokość: | Rozmiar: 185 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 185 KiB Po Szerokość: | Wysokość: | Rozmiar: 185 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 201 KiB Po Szerokość: | Wysokość: | Rozmiar: 201 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 17 KiB Po Szerokość: | Wysokość: | Rozmiar: 17 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 291 KiB Po Szerokość: | Wysokość: | Rozmiar: 291 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 72 KiB Po Szerokość: | Wysokość: | Rozmiar: 72 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 118 KiB Po Szerokość: | Wysokość: | Rozmiar: 118 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 203 KiB Po Szerokość: | Wysokość: | Rozmiar: 203 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 120 KiB Po Szerokość: | Wysokość: | Rozmiar: 120 KiB |
|
@ -1,6 +1,7 @@
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.core.files.storage import default_storage, FileSystemStorage
|
||||||
from django.core.management.base import BaseCommand
|
from django.core.management.base import BaseCommand
|
||||||
from django.core.management import call_command
|
from django.core.management import call_command
|
||||||
|
|
||||||
|
@ -8,10 +9,28 @@ from wagtail.core.models import Site, Page
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
|
def _copy_files(self, local_storage, path):
|
||||||
|
"""
|
||||||
|
Recursively copy files from local_storage to default_storage. Used
|
||||||
|
to automatically bootstrap the media directory (both locally and on
|
||||||
|
cloud providers) with the images linked from the initial data (and
|
||||||
|
included in MEDIA_ROOT).
|
||||||
|
"""
|
||||||
|
directories, file_names = local_storage.listdir(path)
|
||||||
|
for directory in directories:
|
||||||
|
self._copy_files(local_storage, path + directory + '/')
|
||||||
|
for file_name in file_names:
|
||||||
|
with local_storage.open(path + file_name) as file_:
|
||||||
|
default_storage.save(path + file_name, file_)
|
||||||
|
|
||||||
def handle(self, **options):
|
def handle(self, **options):
|
||||||
fixtures_dir = os.path.join(settings.PROJECT_DIR, 'base', 'fixtures')
|
fixtures_dir = os.path.join(settings.PROJECT_DIR, 'base', 'fixtures')
|
||||||
fixture_file = os.path.join(fixtures_dir, 'bakerydemo.json')
|
fixture_file = os.path.join(fixtures_dir, 'bakerydemo.json')
|
||||||
|
|
||||||
|
print("Copying media files to configured storage...")
|
||||||
|
local_storage = FileSystemStorage(os.path.join(fixtures_dir, 'media'))
|
||||||
|
self._copy_files(local_storage, '') # file storage paths are relative
|
||||||
|
|
||||||
# Wagtail creates default Site and Page instances during install, but we already have
|
# Wagtail creates default Site and Page instances during install, but we already have
|
||||||
# them in the data load. Remove the auto-generated ones.
|
# them in the data load. Remove the auto-generated ones.
|
||||||
if Site.objects.filter(hostname='localhost').exists():
|
if Site.objects.filter(hostname='localhost').exists():
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
# Ignore everything in this directory
|
||||||
|
*
|
||||||
|
# Except this file
|
||||||
|
!.gitignore
|
|
@ -29,6 +29,8 @@ services:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: ./Dockerfile
|
dockerfile: ./Dockerfile
|
||||||
|
volumes:
|
||||||
|
- media-root:/code/bakerydemo/media
|
||||||
links:
|
links:
|
||||||
- db:db
|
- db:db
|
||||||
- redis:redis
|
- redis:redis
|
||||||
|
@ -39,3 +41,5 @@ services:
|
||||||
- db
|
- db
|
||||||
- redis
|
- redis
|
||||||
- elasticsearch
|
- elasticsearch
|
||||||
|
volumes:
|
||||||
|
media-root:
|
||||||
|
|
|
@ -188,10 +188,8 @@ environment, set the same environment variables there using the method appropria
|
||||||
|
|
||||||
Once Heroku restarts your application or your Docker container is refreshed, you should have persistent media storage!
|
Once Heroku restarts your application or your Docker container is refreshed, you should have persistent media storage!
|
||||||
|
|
||||||
To copy the initial data included with this demo to the S3 bucket (assuming you ran `./manage.py load_initial_data` per
|
Running `./manage.py load_initial_data` will copy local images to S3, but if you set up S3 after you ran it the first
|
||||||
the above), you can use the AWS CLI included with the requirements:
|
time you might need to run it again.
|
||||||
|
|
||||||
heroku run aws s3 sync bakerydemo/media/original_images/ s3://<bucket-name>/original_images/
|
|
||||||
|
|
||||||
# Next steps
|
# Next steps
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,3 @@ botocore==1.12.33
|
||||||
aws-requests-auth==0.4.0
|
aws-requests-auth==0.4.0
|
||||||
django-redis==4.8.0
|
django-redis==4.8.0
|
||||||
django_cache_url==2.0.0
|
django_cache_url==2.0.0
|
||||||
# For copying initial media to S3 bucket
|
|
||||||
awscli==1.16.43
|
|
||||||
urllib3>=1.21.1,<1.26
|
|
||||||
|
|