Skip to content

Support DatabaseStorage.path for files in database - see #44 #45

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion binary_database_files/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,18 @@ def path(self, name):
"""
localpath = self._path(self.get_instance_name(name))
if not os.path.exists(localpath):
raise NotImplementedError
try:
# Load file from database.
f = models.File.objects.get_from_name(name)
# Automatically write the file to the filesystem
# if it's missing and exists in the database.
# This happens if we're using multiple web servers connected
# to a common database behind a load balancer.
# One user might upload a file from one web server, and then
# another might access if from another server.
utils.write_file(name, f.content)
except models.File.DoesNotExist:
raise NotImplementedError
return localpath

def exists(self, name):
Expand Down
14 changes: 12 additions & 2 deletions binary_database_files/tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,15 +322,13 @@ class Meta:
self.assertTrue(t1.upload.storage.exists(t1.upload.name))
os.remove(t1.upload.path)
self.assertTrue(t1.upload.storage.exists(t1.upload.name))
self.assertRaises(NotImplementedError, lambda t1: t1.upload.path, t1)
data2 = b"22222222"
open(os.path.join(tmpdir, "dummy.txt"), "wb").write(data2)
t2 = Location2Thing.objects.create(
upload=files.File(open(os.path.join(tmpdir, "dummy.txt"), "rb"))
)
os.remove(t2.upload.path)
self.assertTrue(t2.upload.storage.exists(t2.upload.name))
self.assertRaises(NotImplementedError, lambda t2: t2.upload.path, t2)
self.assertEqual(File.objects.count(), 2)
self.assertEqual(Location2Thing.objects.get(pk=t2.pk).upload.file.read(), data2)
self.assertEqual(Location1Thing.objects.get(pk=t1.pk).upload.file.read(), data1)
Expand Down Expand Up @@ -405,6 +403,18 @@ def test_reading_file(self):
self.assertEqual(response["content-type"], "text/plain")
self.assertEqual(response["content-length"], "10")

def test_path_for_file_from_database(self):
call_command("loaddata", "test_files.json")
self.assertEqual(File.objects.count(), 1)
test_fqfn = os.path.join(DIR, "media", "1.txt")
os.remove(test_fqfn)
# File only exists in the database at this point
self.assertFalse(os.path.exists(test_fqfn))
storage = DatabaseStorage()
self.assertEqual(storage.path("1.txt"), test_fqfn)
# File now exists in the filesystem so that it can be accessed directly
self.assertTrue(os.path.exists(test_fqfn))

def test_serve_file_from_database(self):
call_command("loaddata", "test_files.json")
self.assertEqual(File.objects.count(), 1)
Expand Down