From d9cad3036e33c9fa9c0a72ae9759c3599bcb0cfb Mon Sep 17 00:00:00 2001 From: Roger Hunwicks Date: Thu, 15 Jul 2021 15:36:53 +0200 Subject: [PATCH] Support DatabaseStorage.path for files in database - see #44 --- binary_database_files/storage.py | 13 ++++++++++++- binary_database_files/tests/tests.py | 14 ++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/binary_database_files/storage.py b/binary_database_files/storage.py index b918e55..c6830a0 100644 --- a/binary_database_files/storage.py +++ b/binary_database_files/storage.py @@ -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): diff --git a/binary_database_files/tests/tests.py b/binary_database_files/tests/tests.py index 8a4812d..47456e9 100644 --- a/binary_database_files/tests/tests.py +++ b/binary_database_files/tests/tests.py @@ -322,7 +322,6 @@ 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( @@ -330,7 +329,6 @@ class Meta: ) 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) @@ -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)