瀏覽代碼

Added file_hash field to Image

Karl Hobley 7 年之前
父節點
當前提交
507192f5be

+ 18 - 0
wagtail/images/migrations/0021_image_file_hash.py

@@ -0,0 +1,18 @@
+# Generated by Django 2.0.4 on 2018-05-04 15:08
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('wagtailimages', '0020_add-verbose-name'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='image',
+            name='file_hash',
+            field=models.CharField(blank=True, editable=False, max_length=40),
+        ),
+    ]

+ 21 - 2
wagtail/images/models.py

@@ -80,6 +80,8 @@ class AbstractImage(CollectionMember, index.Indexed, models.Model):
     focal_point_height = models.PositiveIntegerField(null=True, blank=True)
 
     file_size = models.PositiveIntegerField(null=True, editable=False)
+    # A SHA-1 hash of the file contents
+    file_hash = models.CharField(max_length=40, blank=True, editable=False)
 
     objects = ImageQuerySet.as_manager()
 
@@ -110,6 +112,18 @@ class AbstractImage(CollectionMember, index.Indexed, models.Model):
 
         return self.file_size
 
+    def _set_file_hash(self, file_contents):
+        self.file_hash = hashlib.sha1(file_contents).hexdigest()
+
+    def get_file_hash(self):
+        if self.file_hash == '':
+            with self.open_file() as f:
+                self._set_file_hash(f.read())
+
+            self.save(update_fields=['file_hash'])
+
+        return self.file_hash
+
     def get_upload_to(self, filename):
         folder_name = 'original_images'
         filename = self.file.field.storage.get_valid_name(filename)
@@ -150,7 +164,7 @@ class AbstractImage(CollectionMember, index.Indexed, models.Model):
         return self.title
 
     @contextmanager
-    def get_willow_image(self):
+    def open_file(self):
         # Open file if it is closed
         close_file = False
         try:
@@ -176,11 +190,16 @@ class AbstractImage(CollectionMember, index.Indexed, models.Model):
         image_file.seek(0)
 
         try:
-            yield WillowImage.open(image_file)
+            yield image_file
         finally:
             if close_file:
                 image_file.close()
 
+    @contextmanager
+    def get_willow_image(self):
+        with self.open_file() as image_file:
+            yield WillowImage.open(image_file)
+
     def get_rect(self):
         return Rect(0, 0, self.width, self.height)
 

+ 12 - 3
wagtail/images/tests/test_admin_views.py

@@ -128,8 +128,9 @@ class TestImageAddView(TestCase, WagtailTestUtils):
         self.assertEqual(image.width, 640)
         self.assertEqual(image.height, 480)
 
-        # Test that the file_size field was set
+        # Test that the file_size/hash fields were set
         self.assertTrue(image.file_size)
+        self.assertTrue(image.file_hash)
 
         # Test that it was placed in the root collection
         root_collection = Collection.get_first_root_node()
@@ -332,8 +333,9 @@ class TestImageEditView(TestCase, WagtailTestUtils):
     def test_edit_with_new_image_file(self):
         file_content = get_test_image_file().file.getvalue()
 
-        # Change the file size of the image
+        # Change the file size/hash of the image
         self.image.file_size = 100000
+        self.image.file_hash = 'abcedf'
         self.image.save()
 
         response = self.post({
@@ -346,13 +348,15 @@ class TestImageEditView(TestCase, WagtailTestUtils):
 
         self.update_from_db()
         self.assertNotEqual(self.image.file_size, 100000)
+        self.assertNotEqual(self.image.file_hash, 'abcedf')
 
     @override_settings(DEFAULT_FILE_STORAGE='wagtail.tests.dummy_external_storage.DummyExternalStorage')
     def test_edit_with_new_image_file_and_external_storage(self):
         file_content = get_test_image_file().file.getvalue()
 
-        # Change the file size of the image
+        # Change the file size/hash of the image
         self.image.file_size = 100000
+        self.image.file_hash = 'abcedf'
         self.image.save()
 
         response = self.post({
@@ -365,6 +369,7 @@ class TestImageEditView(TestCase, WagtailTestUtils):
 
         self.update_from_db()
         self.assertNotEqual(self.image.file_size, 100000)
+        self.assertNotEqual(self.image.file_hash, 'abcedf')
 
     def test_with_missing_image_file(self):
         self.image.file.delete(False)
@@ -704,6 +709,10 @@ class TestImageChooserUploadView(TestCase, WagtailTestUtils):
         self.assertEqual(image.width, 640)
         self.assertEqual(image.height, 480)
 
+        # Test that the file_size/hash fields were set
+        self.assertTrue(image.file_size)
+        self.assertTrue(image.file_hash)
+
     def test_upload_no_file_selected(self):
         response = self.client.post(reverse('wagtailimages:chooser_upload'), {
             'title': "Test image",

+ 7 - 0
wagtail/images/views/chooser.py

@@ -127,6 +127,13 @@ def chooser_upload(request):
         form = ImageForm(request.POST, request.FILES, instance=image, user=request.user)
 
         if form.is_valid():
+            # Set image file size
+            image.file_size = image.file.size
+
+            # Set image file hash
+            image.file.seek(0)
+            image._set_file_hash(image.file.read())
+
             form.save()
 
             # Reindex the image to make sure all tags are indexed

+ 8 - 0
wagtail/images/views/images.py

@@ -101,6 +101,10 @@ def edit(request, image_id):
                 # Set new image file size
                 image.file_size = image.file.size
 
+                # Set new image file hash
+                image.file.seek(0)
+                image._set_file_hash(image.file.read())
+
             form.save()
 
             if 'file' in form.changed_data:
@@ -253,6 +257,10 @@ def add(request):
             # Set image file size
             image.file_size = image.file.size
 
+            # Set image file hash
+            image.file.seek(0)
+            image._set_file_hash(image.file.read())
+
             form.save()
 
             # Reindex the image to make sure all tags are indexed

+ 23 - 0
wagtail/tests/testapp/migrations/0032_auto_20180505_0008.py

@@ -0,0 +1,23 @@
+# Generated by Django 2.0.4 on 2018-05-04 15:08
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('tests', '0031_customdocument_file_size'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='customimage',
+            name='file_hash',
+            field=models.CharField(blank=True, editable=False, max_length=40),
+        ),
+        migrations.AddField(
+            model_name='customimagefilepath',
+            name='file_hash',
+            field=models.CharField(blank=True, editable=False, max_length=40),
+        ),
+    ]