Skip to content

Commit 7035f2b

Browse files
committed
🚚(backend) rename Django storage class for broader file support
Refactored the django-storages class to support various file types beyond videos. This change generalizes storage usage, making it applicable to different file formats.
1 parent 19dbdea commit 7035f2b

34 files changed

+330
-344
lines changed

UPGRADE.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ not skip minor/major releases while upgrading (fix releases can be skipped).
77
The format is inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
88
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
99

10+
### 5.7.x to 5.8.0
11+
12+
Environment variables previously prefixed with `DJANGO_VIDEOS_STORAGE_` are now prefixed with `DJANGO_STORAGE_`. Make sure to update your configuration accordingly.
13+
1014
### 4.2.x to 4.3.0
1115

1216
`DJANGO_STATICFILES_STORAGE` environment variable is not used anymore. You have to replace it by `DJANGO_STORAGES_STATICFILES_BACKEND`.

docker-compose.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ services:
3737
- .:/app
3838
- ./data/static:/data/static
3939
- ./data/media:/data/media
40-
- ./data/videos:/data/videos
40+
- ./data/files:/data/files
4141
depends_on:
4242
- "base"
4343
- "db"
@@ -57,7 +57,7 @@ services:
5757
- .:/app
5858
- ./data/static:/data/static
5959
- ./data/media:/data/media
60-
- ./data/videos:/data/videos
60+
- ./data/files:/data/files
6161
depends_on:
6262
- "base"
6363
- "db"

docs/peertube-runner.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,16 @@ In Marsha app, anything that should be done through Peertube runners should have
3737

3838
In our case we need to set the `STORAGES["videos"]["BACKEND"]` setting with the right storage class, and the `STORAGE_BACKEND` setting with the right value. See [storage](#storage), to understand why we need this second setting.
3939

40-
#### S3VideoStorage
40+
#### S3FileStorage
4141

42-
A storage used to store videos in a S3 like bucket. It can be used locally, and should be used in production.
42+
A storage used to store files in a S3 like bucket. It can be used locally, and should be used in production.
4343

4444
```Python
4545
STORAGES = {
4646
"videos": {
4747
"BACKEND": values.Value(
48-
"marsha.core.storage.s3.S3VideoStorage",
49-
environ_name="STORAGES_VIDEOS_BACKEND",
48+
"marsha.core.storage.s3.S3FileStorage",
49+
environ_name="STORAGES_BACKEND",
5050
),
5151
},
5252
}
@@ -68,8 +68,8 @@ STORAGES = {
6868
),
6969
"OPTIONS": values.DictValue(
7070
{
71-
"location": str(Base.VIDEOS_ROOT),
72-
"base_url": str(Base.VIDEOS_ROOT),
71+
"location": str(Base.FILES_ROOT),
72+
"base_url": str(Base.FILES_ROOT),
7373
},
7474
environ_name="STORAGES_VIDEOS_OPTIONS",
7575
),
@@ -93,7 +93,7 @@ STORAGES = {
9393

9494
#### URLS
9595

96-
When a video object is returned to the client, it contains URLs to access the video playlist and mp4. These URLs are built in the video serializer. Before, they were manually created by combining the cloudfront domain and the video object key. It cannot work anymore because local files cannot be behind a cloudfront domain. BUT, we can simply make use `django-storages` and call the `video_storage.url(key)` method that will return the appropriate URL depending on the class used for videos.
96+
When a video object is returned to the client, it contains URLs to access the video playlist and mp4. These URLs are built in the video serializer. Before, they were manually created by combining the cloudfront domain and the video object key. It cannot work anymore because local files cannot be behind a cloudfront domain. BUT, we can simply make use `django-storages` and call the `storage.url(key)` method that will return the appropriate URL depending on the class used for videos.
9797

9898
### Callbacks
9999

env.d/development.dist

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ DJANGO_AWS_ACCESS_KEY_ID=yourAwsAccesKey
1515
DJANGO_AWS_SECRET_ACCESS_KEY=YourAwsSecretAccessKeyId
1616
DJANGO_AWS_S3_REGION_NAME=eu-west-1
1717

18-
# VIDEOS_STORAGE_S3
19-
DJANGO_VIDEOS_STORAGE_S3_ACCESS_KEY=yourS3AccesKey
20-
DJANGO_VIDEOS_STORAGE_S3_SECRET_KEY=yourS3AccesKey
21-
DJANGO_VIDEOS_STORAGE_S3_ENDPOINT_URL=https://s3.amazonaws.com
22-
DJANGO_VIDEOS_STORAGE_S3_BUCKET_NAME=yourS3BucketName
18+
# STORAGE_S3
19+
DJANGO_STORAGE_S3_ACCESS_KEY=yourS3AccesKey
20+
DJANGO_STORAGE_S3_SECRET_KEY=yourS3AccesKey
21+
DJANGO_STORAGE_S3_ENDPOINT_URL=https://s3.amazonaws.com
22+
DJANGO_STORAGE_S3_BUCKET_NAME=yourS3BucketName
2323

2424
# LTI provider xml configuration (legacy)
2525
DJANGO_LTI_CONFIG_TITLE=Marsha Dev

src/backend/marsha/core/defaults.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -168,12 +168,12 @@
168168
(CELERY_PIPELINE, _("Celery")),
169169
)
170170

171-
VOD_VIDEOS_STORAGE_BASE_DIRECTORY = "vod"
172-
TMP_VIDEOS_STORAGE_BASE_DIRECTORY = "tmp"
173-
DELETED_VIDEOS_STORAGE_BASE_DIRECTORY = "deleted"
174-
175-
VIDEOS_STORAGE_BASE_DIRECTORY = (
176-
(TMP_VIDEOS_STORAGE_BASE_DIRECTORY, _("tmp")),
177-
(VOD_VIDEOS_STORAGE_BASE_DIRECTORY, _("VOD")),
178-
(DELETED_VIDEOS_STORAGE_BASE_DIRECTORY, _("deleted")),
171+
VOD_STORAGE_BASE_DIRECTORY = "vod"
172+
TMP_STORAGE_BASE_DIRECTORY = "tmp"
173+
DELETED_STORAGE_BASE_DIRECTORY = "deleted"
174+
175+
STORAGE_BASE_DIRECTORY = (
176+
(TMP_STORAGE_BASE_DIRECTORY, _("tmp")),
177+
(VOD_STORAGE_BASE_DIRECTORY, _("VOD")),
178+
(DELETED_STORAGE_BASE_DIRECTORY, _("deleted")),
179179
)

src/backend/marsha/core/models/video.py

Lines changed: 43 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
APPROVAL,
2323
CELERY_PIPELINE,
2424
DELETED,
25-
DELETED_VIDEOS_STORAGE_BASE_DIRECTORY,
25+
DELETED_STORAGE_BASE_DIRECTORY,
2626
ENDED,
2727
ERROR,
2828
HARVESTED,
@@ -37,8 +37,8 @@
3737
STOPPING,
3838
TRANSCODE_PIPELINE_CHOICES,
3939
UPLOAD_ERROR_REASON_CHOICES,
40-
VIDEOS_STORAGE_BASE_DIRECTORY,
41-
VOD_VIDEOS_STORAGE_BASE_DIRECTORY,
40+
STORAGE_BASE_DIRECTORY,
41+
VOD_STORAGE_BASE_DIRECTORY,
4242
)
4343
from marsha.core.models.account import ADMINISTRATOR, INSTRUCTOR, OrganizationAccess
4444
from marsha.core.models.base import BaseModel
@@ -314,34 +314,34 @@ def get_source_s3_key(self, stamp=None):
314314
stamp = stamp or self.uploaded_on_stamp()
315315
return f"{self.pk}/video/{self.pk}/{stamp}"
316316

317-
def get_videos_storage_prefix(
317+
def get_storage_prefix(
318318
self,
319319
stamp=None,
320-
base_dir: VIDEOS_STORAGE_BASE_DIRECTORY = VOD_VIDEOS_STORAGE_BASE_DIRECTORY,
320+
base_dir: STORAGE_BASE_DIRECTORY = VOD_STORAGE_BASE_DIRECTORY,
321321
):
322-
"""Compute the videos storage prefix for the video.
322+
"""Compute the storage prefix for the video.
323323
324324
Parameters
325325
----------
326326
stamp: Type[string]
327-
Passing a value for this argument will return the videos storage prefix for the video
327+
Passing a value for this argument will return the storage prefix for the video
328328
assuming its active stamp is set to this value. This is useful to create an upload
329329
policy for this prospective version of the video, so that the client can upload the
330330
file to S3 and the transcodings job can set the `uploaded_on` field to this value.
331331
332-
base: Type[VIDEOS_STORAGE_BASE_DIRECTORY]
333-
The videos storage base directory. Defaults to VOD. It will be used to compute the
334-
videos storage prefix.
332+
base: Type[STORAGE_BASE_DIRECTORY]
333+
The storage base directory. Defaults to VOD. It will be used to compute the
334+
storage prefix.
335335
336336
Returns
337337
-------
338338
string
339-
The videos storage prefix for the video, depending on the base directory passed.
339+
The storage prefix for the video, depending on the base directory passed.
340340
"""
341341
stamp = stamp or self.uploaded_on_stamp()
342342
base = base_dir
343-
if base == DELETED_VIDEOS_STORAGE_BASE_DIRECTORY:
344-
base = f"{base}/{VOD_VIDEOS_STORAGE_BASE_DIRECTORY}"
343+
if base == DELETED_STORAGE_BASE_DIRECTORY:
344+
base = f"{base}/{VOD_STORAGE_BASE_DIRECTORY}"
345345

346346
return f"{base}/{self.pk}/video/{stamp}"
347347

@@ -666,34 +666,34 @@ def get_source_s3_key(self, stamp=None):
666666
mode = f"_{self.mode}" if self.mode else ""
667667
return f"{self.video.pk}/timedtexttrack/{self.pk}/{stamp}_{self.language}{mode}"
668668

669-
def get_videos_storage_prefix(
669+
def get_storage_prefix(
670670
self,
671671
stamp=None,
672-
base_dir: VIDEOS_STORAGE_BASE_DIRECTORY = VOD_VIDEOS_STORAGE_BASE_DIRECTORY,
672+
base_dir: STORAGE_BASE_DIRECTORY = VOD_STORAGE_BASE_DIRECTORY,
673673
):
674-
"""Compute the videos storage prefix for the video.
674+
"""Compute the storage prefix for the video.
675675
676676
Parameters
677677
----------
678678
stamp: Type[string]
679-
Passing a value for this argument will return the videos storage prefix for the video
679+
Passing a value for this argument will return the storage prefix for the video
680680
assuming its active stamp is set to this value. This is useful to create an upload
681681
policy for this prospective version of the video, so that the client can upload the
682682
file to S3 and the transcodings job can set the `uploaded_on` field to this value.
683683
684-
base_dir: Type[VIDEOS_STORAGE_BASE_DIRECTORY]
685-
The videos storage base directory. Defaults to VOD. It will be used to compute the
686-
videos storage prefix.
684+
base_dir: Type[STORAGE_BASE_DIRECTORY]
685+
The storage base directory. Defaults to VOD. It will be used to compute the
686+
storage prefix.
687687
688688
Returns
689689
-------
690690
string
691-
The videos storage prefix for the video, depending on the base directory passed.
691+
The storage prefix for the video, depending on the base directory passed.
692692
"""
693693
stamp = stamp or self.uploaded_on_stamp()
694694
base = base_dir
695-
if base_dir == DELETED_VIDEOS_STORAGE_BASE_DIRECTORY:
696-
base = f"{DELETED_VIDEOS_STORAGE_BASE_DIRECTORY}/{VOD_VIDEOS_STORAGE_BASE_DIRECTORY}"
695+
if base_dir == DELETED_STORAGE_BASE_DIRECTORY:
696+
base = f"{DELETED_STORAGE_BASE_DIRECTORY}/{VOD_STORAGE_BASE_DIRECTORY}"
697697

698698
return f"{base}/{self.video.pk}/timedtext/{self.pk}/{stamp}"
699699

@@ -817,35 +817,35 @@ def get_source_s3_key(self, stamp=None):
817817
stamp = stamp or self.uploaded_on_stamp()
818818
return f"{self.video.pk}/thumbnail/{self.pk}/{stamp}"
819819

820-
def get_videos_storage_prefix(
820+
def get_storage_prefix(
821821
self,
822822
stamp=None,
823-
base_dir: VIDEOS_STORAGE_BASE_DIRECTORY = VOD_VIDEOS_STORAGE_BASE_DIRECTORY,
823+
base_dir: STORAGE_BASE_DIRECTORY = VOD_STORAGE_BASE_DIRECTORY,
824824
):
825-
"""Compute the videos storage prefix for the thumbnail.
825+
"""Compute the storage prefix for the thumbnail.
826826
827827
Parameters
828828
----------
829829
stamp: Type[string]
830-
Passing a value for this argument will return the videos storage prefix for the shared
830+
Passing a value for this argument will return the storage prefix for the shared
831831
live media assuming its active stamp is set to this value. This is useful to create
832832
an upload policy for this prospective version of the thumbnail, so that the
833833
client can upload the file and celery task can set the `uploaded_on` field to this
834834
value.
835835
836-
base_dir: Type[VIDEOS_STORAGE_BASE_DIRECTORY]
837-
The videos storage base directory. Defaults to VOD. It will be used to compute the
838-
videos storage prefix.
836+
base_dir: Type[STORAGE_BASE_DIRECTORY]
837+
The storage base directory. Defaults to VOD. It will be used to compute the
838+
storage prefix.
839839
840840
Returns
841841
-------
842842
string
843-
The videos storage prefix for the thumbnail.
843+
The storage prefix for the thumbnail.
844844
"""
845845
stamp = stamp or self.uploaded_on_stamp()
846846
base = base_dir
847-
if base_dir == DELETED_VIDEOS_STORAGE_BASE_DIRECTORY:
848-
base = f"{DELETED_VIDEOS_STORAGE_BASE_DIRECTORY}/{VOD_VIDEOS_STORAGE_BASE_DIRECTORY}"
847+
if base_dir == DELETED_STORAGE_BASE_DIRECTORY:
848+
base = f"{DELETED_STORAGE_BASE_DIRECTORY}/{VOD_STORAGE_BASE_DIRECTORY}"
849849

850850
return f"{base}/{self.video.pk}/thumbnail/{stamp}"
851851

@@ -1299,35 +1299,35 @@ def get_source_s3_key(self, stamp=None, extension=None):
12991299
stamp = stamp or self.uploaded_on_stamp()
13001300
return f"{self.video.pk}/sharedlivemedia/{self.pk}/{stamp}{extension}"
13011301

1302-
def get_videos_storage_prefix(
1302+
def get_storage_prefix(
13031303
self,
13041304
stamp=None,
1305-
base_dir: VIDEOS_STORAGE_BASE_DIRECTORY = VOD_VIDEOS_STORAGE_BASE_DIRECTORY,
1305+
base_dir: STORAGE_BASE_DIRECTORY = VOD_STORAGE_BASE_DIRECTORY,
13061306
):
1307-
"""Compute the videos storage prefix for the shared live media.
1307+
"""Compute the storage prefix for the shared live media.
13081308
13091309
Parameters
13101310
----------
13111311
stamp: Type[string]
1312-
Passing a value for this argument will return the videos storage prefix for the shared
1312+
Passing a value for this argument will return the storage prefix for the shared
13131313
live media assuming its active stamp is set to this value. This is useful to create
13141314
an upload policy for this prospective version of the shared live media, so that the
13151315
client can upload the file and celery task can set the `uploaded_on` field to this
13161316
value.
13171317
1318-
base_dir: Type[VIDEOS_STORAGE_BASE_DIRECTORY]
1319-
The videos storage base directory. Defaults to VOD. It will be used to compute the
1320-
videos storage prefix.
1318+
base_dir: Type[STORAGE_BASE_DIRECTORY]
1319+
The storage base directory. Defaults to VOD. It will be used to compute the
1320+
storage prefix.
13211321
13221322
Returns
13231323
-------
13241324
string
1325-
The videos storage prefix for the shared live media.
1325+
The storage prefix for the shared live media.
13261326
"""
13271327
stamp = stamp or self.uploaded_on_stamp()
13281328
base = base_dir
1329-
if base_dir == DELETED_VIDEOS_STORAGE_BASE_DIRECTORY:
1330-
base = f"{DELETED_VIDEOS_STORAGE_BASE_DIRECTORY}/{VOD_VIDEOS_STORAGE_BASE_DIRECTORY}"
1329+
if base_dir == DELETED_STORAGE_BASE_DIRECTORY:
1330+
base = f"{DELETED_STORAGE_BASE_DIRECTORY}/{VOD_STORAGE_BASE_DIRECTORY}"
13311331

13321332
return f"{base}/{self.video.pk}/sharedlivemedia/{self.pk}/{stamp}"
13331333

src/backend/marsha/core/serializers/shared_live_media.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
UploadableFileWithExtensionSerializerMixin,
1414
get_video_cloudfront_url_params,
1515
)
16-
from marsha.core.storage.storage_class import video_storage
16+
from marsha.core.storage.storage_class import file_storage
1717
from marsha.core.utils import cloudfront_utils, time_utils
1818

1919

@@ -135,18 +135,18 @@ def get_celery_pipeline_url(self, obj):
135135
urls = {}
136136

137137
stamp = time_utils.to_timestamp(obj.uploaded_on)
138-
base = obj.get_videos_storage_prefix()
138+
base = obj.get_storage_prefix()
139139

140140
pages = {}
141141
for page_number in range(1, obj.nb_pages + 1):
142142
url = f"{base}/{stamp}_{page_number}.svg"
143-
pages[page_number] = video_storage.url(url)
143+
pages[page_number] = file_storage.url(url)
144144

145145
urls["pages"] = pages
146146

147147
if self.context.get("is_admin") or obj.show_download:
148148
url = f"{base}/{stamp}.pdf"
149-
urls["media"] = video_storage.url(url)
149+
urls["media"] = file_storage.url(url)
150150

151151
return urls
152152

src/backend/marsha/core/serializers/thumbnail.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from marsha.core.defaults import CELERY_PIPELINE
99
from marsha.core.models import Thumbnail
1010
from marsha.core.serializers.base import TimestampField
11-
from marsha.core.storage.storage_class import video_storage
11+
from marsha.core.storage.storage_class import file_storage
1212
from marsha.core.utils import time_utils
1313

1414

@@ -115,11 +115,11 @@ def get_urls(self, obj):
115115

116116
if obj.process_pipeline == CELERY_PIPELINE:
117117
stamp = time_utils.to_timestamp(obj.uploaded_on)
118-
base = obj.get_videos_storage_prefix(stamp=stamp)
118+
base = obj.get_storage_prefix(stamp=stamp)
119119

120120
urls = {}
121121
for resolution in settings.VIDEO_RESOLUTIONS:
122-
urls[resolution] = video_storage.url(f"{base}/{resolution}.jpg")
122+
urls[resolution] = file_storage.url(f"{base}/{resolution}.jpg")
123123
return urls
124124

125125
# Default AWS fallback:

src/backend/marsha/core/serializers/timed_text_track.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from marsha.core.defaults import CELERY_PIPELINE
1111
from marsha.core.models import TimedTextTrack
1212
from marsha.core.serializers.base import TimestampField, get_video_cloudfront_url_params
13-
from marsha.core.storage.storage_class import video_storage
13+
from marsha.core.storage.storage_class import file_storage
1414
from marsha.core.utils import cloudfront_utils, time_utils
1515

1616

@@ -146,9 +146,9 @@ def get_source_url(self, obj):
146146
stamp = time_utils.to_timestamp(obj.uploaded_on)
147147

148148
if obj.process_pipeline == CELERY_PIPELINE:
149-
base = obj.get_videos_storage_prefix()
149+
base = obj.get_storage_prefix()
150150

151-
return video_storage.url(f"{base}/source.{obj.extension}")
151+
return file_storage.url(f"{base}/source.{obj.extension}")
152152

153153
# Default AWS fallback
154154
filename = f"{slugify(obj.video.playlist.title)}_{stamp}.{obj.extension}"
@@ -183,9 +183,9 @@ def get_url(self, obj):
183183

184184
if obj.process_pipeline == CELERY_PIPELINE:
185185
stamp = time_utils.to_timestamp(obj.uploaded_on)
186-
base = obj.get_videos_storage_prefix()
186+
base = obj.get_storage_prefix()
187187

188-
return video_storage.url(f"{base}/{stamp}.vtt")
188+
return file_storage.url(f"{base}/{stamp}.vtt")
189189

190190
# Default AWS fallback
191191
url = self._generate_url(obj, "timedtext", extension="vtt")

0 commit comments

Comments
 (0)