Skip to content

Commit 7cd0601

Browse files
committed
fix kimetrica#65: handle empty MEDIA_ROOT settings and add settings checks
1 parent d4f9b5b commit 7cd0601

File tree

3 files changed

+54
-7
lines changed

3 files changed

+54
-7
lines changed

binary_database_files/apps.py

+24
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
from django.apps import AppConfig
2+
from django.conf import settings
3+
from django.core.checks import Error, register
24

35

46
class DatabaseFilesAppConfig(AppConfig):
@@ -7,3 +9,25 @@ class DatabaseFilesAppConfig(AppConfig):
79
name = "binary_database_files"
810
label = "binary_database_files"
911
verbose_name = "django-binary-database-files"
12+
13+
14+
@register()
15+
def check_settings(app_configs, **kwargs):
16+
errors = []
17+
if not settings.MEDIA_ROOT and settings.DATABASE_FILES_URL_METHOD_NAME == "URL_METHOD_1":
18+
errors.append(
19+
Error(
20+
"MEDIA_ROOT is not defined, yet you are using URL_METHOD_1 which serves media files from the filesystem.",
21+
hint="If you intend to only serve files from the database, use URL_METHOD_2.",
22+
id="binary_database_files.E001",
23+
)
24+
)
25+
if not settings.MEDIA_ROOT and settings.DB_FILES_AUTO_EXPORT_DB_TO_FS:
26+
errors.append(
27+
Error(
28+
"MEDIA_ROOT is not defined, yet you are using DB_FILES_AUTO_EXPORT_DB_TO_FS which copies media files from the filesystem.",
29+
hint="If you intend to only serve files from the database, set DB_FILES_AUTO_EXPORT_DB_TO_FS to False.",
30+
id="binary_database_files.E002",
31+
)
32+
)
33+
return errors

binary_database_files/tests/tests.py

+18
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66
from io import BytesIO
77
from zipfile import ZipFile
88

9+
from django.conf import global_settings
910
from django.conf import settings
1011
from django.core import files
1112
from django.core.files import File as DjangoFile
1213
from django.core.files.base import ContentFile
1314
from django.core.files.storage import default_storage
1415
from django.core.files.temp import NamedTemporaryFile
1516
from django.core.management import call_command
17+
from django.core.management.base import SystemCheckError
1618
from django.db import models
1719
from django.test import TestCase, override_settings
1820

@@ -420,3 +422,19 @@ def test_serve_file_from_database(self):
420422
self.assertEqual(content, b"1234567890")
421423
self.assertEqual(response["content-type"], "text/plain")
422424
self.assertEqual(response["content-length"], "10")
425+
426+
@override_settings(
427+
MEDIA_ROOT=global_settings.MEDIA_ROOT,
428+
DATABASE_FILES_URL_METHOD_NAME = "URL_METHOD_1", # default
429+
DB_FILES_AUTO_EXPORT_DB_TO_FS = True, # default
430+
)
431+
def test_refuse_unset_media_root(self):
432+
# regression test for issue #65 where unset MEDIA_ROOT would result in serving the source code
433+
434+
message_a = "(binary_database_files.E001) MEDIA_ROOT is not defined, yet you are using URL_METHOD_1 which serves media files from the filesystem"
435+
with self.assertRaisesMessage(SystemCheckError, message_a):
436+
call_command("check")
437+
438+
message_b = "(binary_database_files.E002) MEDIA_ROOT is not defined, yet you are using DB_FILES_AUTO_EXPORT_DB_TO_FS which copies media files from the filesystem."
439+
with self.assertRaisesMessage(SystemCheckError, message_b):
440+
call_command("check")

binary_database_files/views.py

+12-7
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,20 @@ def serve(request, name):
2727

2828
def serve_mixed(request, *args, **kwargs):
2929
"""
30-
First attempts to serve the file from the filesystem,
30+
If document_root or MEDIA_ROOT is set, attempts to serve the file from the filesystem,
3131
then tries the database.
3232
"""
3333
name = kwargs.get("name") or kwargs.get("path")
3434
document_root = kwargs.get("document_root")
3535
document_root = document_root or settings.MEDIA_ROOT
36-
try:
37-
# First attempt to serve from filesystem.
38-
return django_serve(request, name, document_root)
39-
except Http404:
40-
# Then try serving from database.
41-
return serve(request, name)
36+
37+
# empty document_root would result in serving the source code
38+
if document_root:
39+
try:
40+
# First attempt to serve from filesystem.
41+
return django_serve(request, name, document_root)
42+
except Http404:
43+
pass
44+
45+
# Then try serving from database.
46+
return serve(request, name)

0 commit comments

Comments
 (0)