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
|
from django.db import models
from django.core.exceptions import ValidationError
from .forms import ImageBinaryFormField, PdfBinaryFormField
from PIL import ImageFile
from postgresqleu.util.magic import magicdb
class LowercaseEmailField(models.EmailField):
def get_prep_value(self, value):
value = super(models.EmailField, self).get_prep_value(value)
if value is not None:
value = value.lower()
return value
class ImageBinaryField(models.Field):
empty_values = [None, b'']
def __init__(self, max_length, *args, **kwargs):
self.max_resolution = kwargs.pop('max_resolution', None)
super(ImageBinaryField, self).__init__(*args, **kwargs)
self.max_length = max_length
def deconstruct(self):
name, path, args, kwargs = super(ImageBinaryField, self).deconstruct()
return name, path, args, kwargs
def get_internal_type(self):
return "ImageBinaryField"
def get_placeholder(self, value, compiler, connection):
return '%s'
def get_default(self):
return b''
def db_type(self, connection):
return 'bytea'
def get_db_prep_value(self, value, connection, prepared=False):
value = super(ImageBinaryField, self).get_db_prep_value(value, connection, prepared)
if value is not None:
return connection.Database.Binary(value)
return value
def value_to_string(self, obj):
"""Binary data is serialized as base64"""
return b64encode(force_bytes(self.value_from_object(obj))).decode('ascii')
def to_python(self, value):
if self.max_length is not None and len(value) > self.max_length:
raise ValidationError("Maximum size of file is {} bytes".format(self.max_length))
if isinstance(value, memoryview):
v = bytes(value)
else:
v = value
try:
p = ImageFile.Parser()
p.feed(v)
p.close()
img = p.image
except Exception as e:
raise ValidationError("Could not parse image: %s" % e)
if img.format.upper() != 'JPEG':
raise ValidationError("Only JPEG files are allowed")
if self.max_resolution:
if img.size[0] > self.max_resolution[0] or img.size[1] > self.max_resolution[1]:
raise ValidationError("Maximum image size is {}x{}".format(*self.max_resolution))
return value
def save_form_data(self, instance, data):
if data is not None:
if not data:
data = b''
setattr(instance, self.name, data)
def formfield(self, **kwargs):
defaults = {'form_class': ImageBinaryFormField}
defaults.update(kwargs)
return super(ImageBinaryField, self).formfield(**defaults)
class PdfBinaryField(ImageBinaryField):
def get_internal_type(self):
return "PdfBinaryField"
def formfield(self, **kwargs):
defaults = {'form_class': PdfBinaryFormField}
defaults.update(kwargs)
return super(PdfBinaryField, self).formfield(**defaults)
def to_python(self, value):
if self.max_length is not None and len(value) > self.max_length:
raise ValidationError("Maximum size of file is {} bytes".format(self.max_length))
mtype = magicdb.buffer(value)
if not mtype.startswith('application/pdf'):
raise ValidationError("File must be PDF, not %s" % mtype)
return value
|