|
|
@@ -1,56 +1,84 @@
|
|
1
|
1
|
import os
|
|
2
|
|
-
|
|
3
|
2
|
from PIL import Image as PImage
|
|
4
|
3
|
|
|
5
|
4
|
from django.core.files import File
|
|
6
|
5
|
from django.core.exceptions import FieldError
|
|
7
|
6
|
|
|
8
|
7
|
from oscar.core.loading import import_module
|
|
9
|
|
-
|
|
10
|
|
-import_module('image.exceptions', ['ImageImportException'], locals())
|
|
|
8
|
+import_module('image.exceptions', ['ImageImportException', 'IdenticalImageException'], locals())
|
|
11
|
9
|
import_module('product.models', ['Item'], locals())
|
|
12
|
10
|
import_module('image.models', ['Image'], locals())
|
|
13
|
11
|
|
|
|
12
|
+
|
|
14
|
13
|
class Importer(object):
|
|
15
|
14
|
|
|
|
15
|
+ allowed_extensions = ['.jpeg','.jpg','.gif','.png']
|
|
|
16
|
+
|
|
16
|
17
|
def __init__(self, logger, field):
|
|
17
|
18
|
self.logger = logger
|
|
18
|
19
|
self._field = field
|
|
19
|
20
|
|
|
20
|
|
- def handle(self, filename, dirname):
|
|
|
21
|
+ def handle(self, dirname):
|
|
|
22
|
+ stats = {
|
|
|
23
|
+ 'num_processed': 0,
|
|
|
24
|
+ 'num_skipped': 0,
|
|
|
25
|
+ 'num_invalid': 0
|
|
|
26
|
+ }
|
|
|
27
|
+ for filename in self._get_image_files(dirname):
|
|
|
28
|
+ try:
|
|
|
29
|
+ lookup_value = self._get_lookup_value_from_filename(filename)
|
|
|
30
|
+ self._process_image(dirname, filename, lookup_value)
|
|
|
31
|
+ stats['num_processed'] += 1
|
|
|
32
|
+ except Item.MultipleObjectsReturned:
|
|
|
33
|
+ self.logger.warning("Multiple products matching %s='%s', skipping" % (self._field, lookup_value))
|
|
|
34
|
+ stats['num_skipped'] += 1
|
|
|
35
|
+ except Item.DoesNotExist:
|
|
|
36
|
+ self.logger.warning("No item matching %s='%s'" % (self._field, lookup_value))
|
|
|
37
|
+ stats['num_skipped'] += 1
|
|
|
38
|
+ except IdenticalImageException:
|
|
|
39
|
+ self.logger.warning(" - Identical image already exists for %s='%s', skipping" % (self._field, lookup_value))
|
|
|
40
|
+ stats['num_skipped'] += 1
|
|
|
41
|
+ except IOError:
|
|
|
42
|
+ raise ImageImportException('%s is not a valid image' % filename)
|
|
|
43
|
+ stats['num_invalid'] += 1
|
|
|
44
|
+ except FieldError, e:
|
|
|
45
|
+ raise ImageImportException(e)
|
|
|
46
|
+ self._process_image(dirname, filename)
|
|
|
47
|
+ self.logger.info("Finished image import: %(num_processed)d imported, %(num_skipped)d skipped" % stats)
|
|
21
|
48
|
|
|
22
|
|
- f = os.path.join(dirname,filename)
|
|
|
49
|
+ def _get_image_files(self, dirname):
|
|
|
50
|
+ filenames = []
|
|
|
51
|
+ for filename in os.listdir(dirname):
|
|
|
52
|
+ ext = os.path.splitext(filename)[1]
|
|
|
53
|
+ if os.path.isfile(os.path.join(dirname, filename)) and ext in self.allowed_extensions:
|
|
|
54
|
+ filenames.append(filename)
|
|
|
55
|
+ return filenames
|
|
|
56
|
+
|
|
|
57
|
+ def _process_image(self, dirname, filename, lookup_value):
|
|
|
58
|
+ file_path = os.path.join(dirname, filename)
|
|
|
59
|
+ trial_image = PImage.open(file_path)
|
|
|
60
|
+ trial_image.verify()
|
|
23
|
61
|
|
|
24
|
|
- kwargs = {}
|
|
25
|
|
- kwargs[self._field] = os.path.splitext(filename)[0]
|
|
|
62
|
+ kwargs = {self._field: lookup_value}
|
|
|
63
|
+ item = Item._default_manager.get(**kwargs)
|
|
26
|
64
|
|
|
27
|
|
- try:
|
|
28
|
|
- item = Item.objects.get(**kwargs)
|
|
29
|
|
-
|
|
30
|
|
- create_new = True
|
|
31
|
|
- max_index = 0
|
|
|
65
|
+ new_data = open(file_path).read()
|
|
|
66
|
+ next_index = 0
|
|
|
67
|
+ for existing in item.images.all():
|
|
|
68
|
+ next_index = existing.display_order + 1
|
|
|
69
|
+ if new_data == existing.original.read():
|
|
|
70
|
+ raise IdenticalImageException()
|
|
32
|
71
|
|
|
33
|
|
- new_data = open(f).read()
|
|
34
|
|
-
|
|
35
|
|
- trial_image = PImage.open(f)
|
|
36
|
|
- trial_image.verify()
|
|
37
|
|
-
|
|
38
|
|
- # if this image already exists for the Item, ignore it
|
|
39
|
|
- for existing in item.images.all():
|
|
40
|
|
- max_index = existing.display_order + 1
|
|
41
|
|
- if new_data == existing.original.read():
|
|
42
|
|
- create_new = False
|
|
43
|
|
- break
|
|
44
|
|
-
|
|
45
|
|
- if create_new:
|
|
46
|
|
- new_file = File(open(f))
|
|
47
|
|
- im = Image(product=item,display_order=max_index)
|
|
48
|
|
- im.original.save(filename, new_file, save=False)
|
|
49
|
|
- im.save()
|
|
50
|
|
- self.logger.info('image added to "%s"' % item)
|
|
51
|
|
- except IOError:
|
|
52
|
|
- raise ImageImportException('%s is not a valid image' % filename)
|
|
53
|
|
- except (Item.MultipleObjectsReturned, Item.DoesNotExist):
|
|
54
|
|
- pass # We don't care
|
|
55
|
|
- except FieldError, e:
|
|
56
|
|
- raise ImageImportException(e)
|
|
|
72
|
+ new_file = File(open(file_path))
|
|
|
73
|
+ im = Image(product=item, display_order=next_index)
|
|
|
74
|
+ im.original.save(filename, new_file, save=False)
|
|
|
75
|
+ im.save()
|
|
|
76
|
+ self.logger.info(' - Image added to "%s"' % item)
|
|
|
77
|
+
|
|
|
78
|
+ def _fetch_item(self, filename):
|
|
|
79
|
+ kwargs = {self._field: self._get_lookup_value_from_filename(filename)}
|
|
|
80
|
+ return Item._default_manager.get(**kwargs)
|
|
|
81
|
+
|
|
|
82
|
+ def _get_lookup_value_from_filename(self, filename):
|
|
|
83
|
+ return os.path.splitext(filename)[0]
|
|
|
84
|
+
|