diff --git a/dbfilestorage/migrations/0005_auto_20170127_2037.py b/dbfilestorage/migrations/0005_auto_20170127_2037.py new file mode 100644 index 0000000..0734086 --- /dev/null +++ b/dbfilestorage/migrations/0005_auto_20170127_2037.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.4 on 2017-01-27 20:37 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dbfilestorage', '0004_dbfile_mtime'), + ] + + operations = [ + migrations.AlterField( + model_name='dbfile', + name='filehash', + field=models.CharField(max_length=32), + ), + migrations.AlterField( + model_name='dbfile', + name='name', + field=models.CharField(max_length=100, primary_key=True, serialize=False), + ), + ] diff --git a/dbfilestorage/migrations/0006_remove_dbfile_filehash.py b/dbfilestorage/migrations/0006_remove_dbfile_filehash.py new file mode 100644 index 0000000..50ad269 --- /dev/null +++ b/dbfilestorage/migrations/0006_remove_dbfile_filehash.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.4 on 2017-01-27 20:42 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('dbfilestorage', '0005_auto_20170127_2037'), + ] + + operations = [ + migrations.RemoveField( + model_name='dbfile', + name='filehash', + ), + ] diff --git a/dbfilestorage/models.py b/dbfilestorage/models.py index 82d5bc6..cd2d56e 100644 --- a/dbfilestorage/models.py +++ b/dbfilestorage/models.py @@ -7,8 +7,7 @@ class DBFile(models.Model): # This is kept as `name` and not something like `md5` because the file # operations pass around `name` as the identifier, so it's kept the same # to make sense. - name = models.CharField(max_length=100) - filehash = models.CharField(max_length=32, primary_key=True) + name = models.CharField(max_length=100, primary_key=True) # file data content_type = models.CharField(max_length=100) @@ -16,8 +15,8 @@ class DBFile(models.Model): mtime = models.DateTimeField(auto_now=True) def __unicode__(self): - return u"{filehash} <{content_type}>".format( - filehash=self.filehash, content_type=self.content_type) + return u"{name} <{content_type}>".format( + name=self.name, content_type=self.content_type) def save(self, **kwargs): if self.content_type is None: diff --git a/dbfilestorage/storage.py b/dbfilestorage/storage.py index c1b98ce..0800245 100644 --- a/dbfilestorage/storage.py +++ b/dbfilestorage/storage.py @@ -1,6 +1,5 @@ import mimetypes import logging -import hashlib import os from django.db.transaction import atomic @@ -15,7 +14,7 @@ L = logging.getLogger(__name__) def _get_object(param): - return DBFile.objects.filter(Q(name=param) | Q(filehash=param)).first() + return DBFile.objects.filter(name=param).first() class DBFileStorage(Storage): @@ -55,21 +54,12 @@ class DBFileStorage(Storage): # USE mimetypes.guess_type as an attempt at getting the content type. ct = mimetypes.guess_type(name)[0] - # After we get the mimetype by name potentially, mangle it. - filehash = hashlib.md5(read_data).hexdigest() - - file_ext = os.path.splitext(name)[1] - if not file_ext: - file_ext = ".txt" - # create the file, or just return name if the exact file already exists - if not DBFile.objects.filter(filehash=filehash, name=name).exists(): - the_file = DBFile( + if not DBFile.objects.filter(name=name).exists(): + the_file = DBFile.objects.create( name=name, - filehash=filehash, content_type=ct, b64=b64) - the_file.save() return name def get_available_name(self, name, max_length=None): @@ -82,7 +72,7 @@ class DBFileStorage(Storage): DBFile.objects.filter(pk=name).delete() def exists(self, name): - return DBFile.objects.filter(Q(name=name) | Q(filehash=name)).exists() + return DBFile.objects.filter(name=name).exists() def size(self, name): dbf = _get_object(name) diff --git a/dbfilestorage/views.py b/dbfilestorage/views.py index 77c311d..dd8db44 100644 --- a/dbfilestorage/views.py +++ b/dbfilestorage/views.py @@ -13,12 +13,10 @@ def show_file(request, name): :return HttpResponse: Rendered file """ - dbf = DBFile.objects.filter(Q(name=name)|Q(filehash=name)) - if dbf.exists(): - response = HttpResponse( - dbf[0].b64.decode('base64'), - content_type=dbf[0].content_type) - response['Content-Disposition'] = 'attachment; filename="{}"'.format( - dbf[0].name) - return response - raise Http404 + dbf = get_object_or_404(DBFile, name=name) + response = HttpResponse( + dbf.b64.decode('base64'), + content_type=dbf.content_type) + response['Content-Disposition'] = 'attachment; filename="{}"'.format( + dbf.name) + return response diff --git a/tests/tests.py b/tests/tests.py index 72f48e0..0b6f9d6 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -import hashlib import os from dbfilestorage.models import DBFile @@ -21,7 +20,6 @@ class DBFileTest(TestCase): def setUp(self): self.filename = "kris.jpg" self.filepath = os.path.join(PROJECT_ROOT, "test_files", self.filename) - self.md5 = hashlib.md5(open(self.filepath, 'rb').read()).hexdigest() self._upload() @@ -31,16 +29,15 @@ class DBFileTest(TestCase): def test_upload(self): """ Test that the file storage uploads and puts in DB Properly """ - self.assertTrue(DBFile.objects.filter(filehash=self.md5).exists()) + self.assertTrue(DBFile.objects.filter(name=self.filepath).exists()) def test_content_file(self): """ Test that this code works with ContentFile as well """ content_file = ContentFile(u"ΑΔΔGΕΝΕ") - content_file_md5 = hashlib.md5(u"ΑΔΔGΕΝΕ".encode('utf8')).hexdigest() default_storage.save("unicode", content_file) - unicode_file = DBFile.objects.get(filehash=content_file_md5) + unicode_file = DBFile.objects.get(name="unicode") self.assertEqual(unicode(unicode_file), - "{} ".format(content_file_md5)) + "unicode ") def test_no_duplicate_upload(self): """ Test that it won't make a new file if it already exists """ @@ -51,25 +48,25 @@ class DBFileTest(TestCase): def test_equality(self): """ Test that the DB entry matches what is expected from the file """ with open(self.filepath, 'rb') as f: - dbf = DBFile.objects.get(filehash=self.md5) + dbf = DBFile.objects.get(name=self.filepath) self.assertEqual(dbf.b64.decode("base64"), f.read()) self.assertEqual(dbf.content_type, 'image/jpeg') def test_open(self): """ Test that the storage mechanism can upload """ - dbf = default_storage.open(self.md5) + dbf = default_storage.open(self.filepath) with open(self.filepath, 'rb') as f: self.assertEqual(dbf.read(), f.read()) def test_exists(self): """ Test that the storage mechanism can check existance """ - self.assertTrue(default_storage.exists(self.md5)) + self.assertTrue(default_storage.exists(self.filepath)) def test_delete(self): """ Test Deletion """ - self.assertTrue(DBFile.objects.filter(filehash=self.md5).exists()) - default_storage.delete(self.md5) - self.assertFalse(DBFile.objects.filter(filehash=self.md5).exists()) + self.assertTrue(DBFile.objects.filter(name=self.filepath).exists()) + default_storage.delete(self.filepath) + self.assertFalse(DBFile.objects.filter(name=self.filepath).exists()) # Also test that calling delete on something that doesn't exist, # errors silently self.assertFalse(DBFile.objects.filter(name="Nothing").exists()) @@ -77,20 +74,18 @@ class DBFileTest(TestCase): def test_size(self): """ Ensure we can get the proper size """ - size = default_storage.size(self.md5) + size = default_storage.size(self.filepath) self.assertGreater(size, 0) def test_url(self): - """ Test that the url returned is the md5 path not the filename """ - self.assertIn(self.filename, default_storage.url(self.md5)) + """ Test that the url returned is the filename """ + self.assertIn(self.filename, default_storage.url(self.filename)) def test_view(self): client = Client() - # check it works for both md5 and filename - for param in (self.md5, self.filepath): - url = default_storage.url(param) - resp = client.get(url) - self.assertEqual(resp.status_code, 200) + url = default_storage.url(self.filepath) + resp = client.get(url) + self.assertEqual(resp.status_code, 200) def test_view_fails(self): client = Client() @@ -107,7 +102,7 @@ class DBFileTest(TestCase): client.login(username=my_admin.username, password='top_secret') url = reverse("admin:dbfilestorage_dbfile_changelist") resp = client.get(url) - self.assertContains(resp, self.md5) + self.assertContains(resp, self.filepath) def test_mtime(self): """ Ensure we can get the modified time """