1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134 | import re
import os
re_thumbnail_file = re.compile(r'(?P<source_filename>.+)_(?P<x>\d+)x(?P<y>\d+)(?:_(?P<options>\w+))?_q(?P<quality>\d+)(?:.[^.]+)?$')
def all_thumbnails(path, recursive=True, prefix=None, subdir=None):
"""
Return a dictionary referencing all files which match the thumbnail format.
Each key is a source image filename, relative to path.
Each value is a list of dictionaries as explained in `thumbnails_for_file`.
"""
# Fall back to using thumbnail settings. These are local imports so that
# there is no requirement of Django to use the utils module.
if prefix is None:
from sorl.thumbnail.main import get_thumbnail_setting
prefix = get_thumbnail_setting('PREFIX')
if subdir is None:
from sorl.thumbnail.main import get_thumbnail_setting
subdir = get_thumbnail_setting('SUBDIR')
thumbnail_files = {}
if not path.endswith('/'):
path = '%s/' % path
len_path = len(path)
if recursive:
all = os.walk(path)
else:
files = []
for file in os.listdir(path):
if os.path.isfile(os.path.join(path, file)):
files.append(file)
all = [(path, [], files)]
for dir_, subdirs, files in all:
rel_dir = dir_[len_path:]
for file in files:
thumb = re_thumbnail_file.match(file)
if not thumb:
continue
d = thumb.groupdict()
source_filename = d.pop('source_filename')
if prefix:
source_path, source_filename = os.path.split(source_filename)
if not source_filename.startswith(prefix):
continue
source_filename = os.path.join(source_path,
source_filename[len(prefix):])
d['options'] = d['options'] and d['options'].split('_') or []
if subdir and rel_dir.endswith(subdir):
rel_dir = rel_dir[:-len(subdir)]
# Corner-case bug: if the filename didn't have an extension but did
# have an underscore, the last underscore will get converted to a
# '.'.
m = re.match(r'(.*)_(.*)', source_filename)
if m:
source_filename = '%s.%s' % m.groups()
filename = os.path.join(rel_dir, source_filename)
thumbnail_file = thumbnail_files.setdefault(filename, [])
d['filename'] = os.path.join(dir_, file)
thumbnail_file.append(d)
return thumbnail_files
def thumbnails_for_file(relative_source_path, root=None, basedir=None,
subdir=None, prefix=None):
"""
Return a list of dictionaries, one for each thumbnail belonging to the
source image.
The following list explains each key of the dictionary:
`filename` -- absolute thumbnail path
`x` and `y` -- the size of the thumbnail
`options` -- list of options for this thumbnail
`quality` -- quality setting for this thumbnail
"""
# Fall back to using thumbnail settings. These are local imports so that
# there is no requirement of Django to use the utils module.
if root is None:
from django.conf import settings
root = settings.MEDIA_ROOT
if prefix is None:
from sorl.thumbnail.main import get_thumbnail_setting
prefix = get_thumbnail_setting('PREFIX')
if subdir is None:
from sorl.thumbnail.main import get_thumbnail_setting
subdir = get_thumbnail_setting('SUBDIR')
if basedir is None:
from sorl.thumbnail.main import get_thumbnail_setting
basedir = get_thumbnail_setting('BASEDIR')
source_dir, filename = os.path.split(relative_source_path)
thumbs_path = os.path.join(root, basedir, source_dir, subdir)
if not os.path.isdir(thumbs_path):
return []
files = all_thumbnails(thumbs_path, recursive=False, prefix=prefix,
subdir='')
return files.get(filename, [])
def delete_thumbnails(relative_source_path, root=None, basedir=None,
subdir=None, prefix=None):
"""
Delete all thumbnails for a source image.
"""
thumbs = thumbnails_for_file(relative_source_path, root, basedir, subdir,
prefix)
return _delete_using_thumbs_list(thumbs)
def _delete_using_thumbs_list(thumbs):
deleted = 0
for thumb_dict in thumbs:
filename = thumb_dict['filename']
try:
os.remove(filename)
except:
pass
else:
deleted += 1
return deleted
def delete_all_thumbnails(path, recursive=True):
"""
Delete all files within a path which match the thumbnails pattern.
By default, matching files from all sub-directories are also removed. To
only remove from the path directory, set recursive=False.
"""
total = 0
for thumbs in all_thumbnails(path, recursive=recursive).values():
total += _delete_using_thumbs_list(thumbs)
return total
|