Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# Imports 

2 

3from django.conf import settings 

4from myninjas.utils import File 

5import os 

6from PIL import Image 

7from unidecode import unidecode 

8from .constants import ALLOWED_CHARACTERS 

9 

10# Exports 

11 

12__all__ = ( 

13 "generate_thumbnail", 

14 "get_unique_file_name", 

15 "get_upload_to", 

16 "remove_non_ascii", 

17 "sanitize", 

18) 

19 

20# Constants 

21 

22UPLOAD_DIR = getattr(settings, "SUPERDJANGO_UPLOAD_DIR", "uploads") 

23 

24# Functions 

25 

26 

27def generate_thumbnail(path, height=200, prefix=None, suffix="thumbnail", width=200): 

28 """Generate a thumbnail for the given image file. 

29 

30 :param path: The path to the image file. 

31 :type path: str 

32 

33 :param height: The height of the thumbnail image. 

34 :type height: int 

35 

36 :param prefix: The prefix of the new thumbnail file. The width and height will be added to the prefix in the form of 

37 ``prefix-WxH-file.extension``. 

38 :type prefix: str 

39 

40 :param suffix: The suffix of the new thumbnail file. The width and height will be added to the suffix in the form of 

41 ``file-suffix-WxH.extension``. 

42 :type suffix: str 

43 

44 :param width: The width of the thumbnail image. 

45 :type width: int 

46 

47 :rtype: str 

48 :returns: The path of the thumbnail file relative to ``MEDIA_ROOT``. 

49 

50 .. note:: 

51 Either the prefix or suffix is used in the new file name, but not both. 

52 

53 """ 

54 file = File(path) 

55 

56 a = list() 

57 if prefix is not None: 

58 a.append(prefix) 

59 a.append("%sx%s" % (width, height)) 

60 a.append("%s%s" % (file.name, file.extension)) 

61 else: 

62 a.append(file.name) 

63 a.append(suffix) 

64 a.append("%sx%s%s" % (width, height, file.extension)) 

65 

66 new_file_name = "-".join(a) 

67 new_path = os.path.join(file.directory, new_file_name) 

68 

69 image = Image.open(path) 

70 image.thumbnail((width, height)) 

71 image.save(new_path) 

72 

73 partial = new_path.replace(settings.MEDIA_ROOT, "") 

74 if partial.startswith("/"): 

75 partial = partial[1:] 

76 

77 return partial 

78 

79 

80def get_unique_file_name(file_name): 

81 """Given a file name to be uploaded, get a unique name if the file already exists. 

82 

83 :param file_name: The name of the file to be checked. 

84 :type file_name: str 

85 

86 :rtype: str 

87 

88 """ 

89 # First, clean up the name. 

90 file_name = sanitize(file_name) 

91 

92 # The name is unique if the file doesn't already exist. 

93 path = os.path.join(settings.MEDIA_ROOT, UPLOAD_DIR, file_name) 

94 if not os.path.exists(path): 

95 return file_name 

96 

97 # Now find a unique name. 

98 suffix = 1 

99 while True: 

100 file_name = "%s-%s" % (suffix, file_name) 

101 path = os.path.join(settings.MEDIA_ROOT, UPLOAD_DIR, file_name) 

102 if not os.path.exists(path): 

103 return file_name 

104 

105 

106def get_upload_to(instance, filename): 

107 """Get the path to upload a content file. 

108 

109 :param instance: The model instance. 

110 

111 :param filename: The name of the file. 

112 :type filename: str 

113 

114 :rtype: str 

115 

116 .. important:: 

117 The model instance must implement a ``get_upload_to()`` method. 

118 

119 This allows the actual work of acquiring the upload path to be performed on the model where the file is defined. 

120 

121 .. code-block:: python 

122  

123 from superdjango.storage import import get_upload_to, remove_non_ascii 

124  

125 class Document(models.Model): 

126  

127 file = models.FileField( 

128 _("file"), 

129 help_text=_("Select the file to upload."), 

130 upload_to=get_upload_to 

131 ) 

132 

133 def get_upload_to(self, filename): 

134 file_name = self.file.field.storage.get_valid_name(filename) 

135 file_name = remove_non_ascii(file_name) 

136 

137 directory_name = "documents" 

138 path = os.path.join(directory_name, file_name) 

139 

140 return path 

141 

142 """ 

143 return instance.get_upload_to(filename) 

144 

145 

146def remove_non_ascii(text): 

147 """Replace non-ASCII characters with ASCII characters. 

148 

149 :param text: The string that should have non-ASCII characters removed. 

150 :type text: str 

151 

152 :rtype: str 

153 

154 """ 

155 return unidecode(str(text)) 

156 

157 

158def sanitize(file_name): 

159 """Make sure a given file name has no spaces or special characters. 

160 

161 :param file_name: The file name to be sanitized. Do NOT include the path. 

162 :type file_name: str 

163 

164 :rtype: str 

165 

166 """ 

167 file_name = remove_non_ascii(file_name) 

168 

169 file_name = file_name.replace(" ", "-") 

170 

171 a = list() 

172 for c in file_name: 

173 if c not in ALLOWED_CHARACTERS: 

174 continue 

175 

176 a.append(c) 

177 

178 return ''.join(a)