-
Notifications
You must be signed in to change notification settings - Fork 0
/
fields.py
91 lines (75 loc) · 2.81 KB
/
fields.py
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
import os
import os.path as op
from fsfield.core import model_instance_field_path, default_storage
class FileStorageFieldDescriptor(object):
def __init__(self, name, storage, default, load, dump):
self.name = name
self.storage = storage
self.default = default
self.load = load
self.dump = dump
def path(self, obj):
return model_instance_field_path(obj, self.name)
def __get__(self, obj, type=None):
if obj is None:
return
if obj.pk is None:
raise ValueError("you must save the object to the database before "
"accessing this field")
path = self.path(obj)
if not self.storage.exists(path):
return self.default
fp = self.storage.open(path, "rb")
if self.load is not None:
return self.load(fp)
return fp.read()
def __set__(self, obj, value):
if obj is None:
return
if obj.pk is None:
raise ValueError("you must save the object to the database before "
"accessing this field")
path = self.path(obj)
directory = op.dirname(self.storage.path(path))
if not op.isdir(directory):
os.makedirs(directory)
fp = self.storage.open(path, "wb")
if self.dump is not None:
self.dump(value, fp)
else:
fp.write(value)
class FileStorageField(object):
"""
This field type stores string data on the disk, bypassing entirely the
database.
*storage* may be a :class:`~django.core.files.storage.Storage` subclass to
customize where the files are stored. The default storage is used if this
is left unspecified.
You may specify callables in *load* and *dump* to alter the way data is
loaded from and saved to disk::
load(fp)
dump(data, fp)
Where ``fp`` is a file-like object returned by the storage system.
*default* is the value returned when the file associated to the field
doesn't exist.
*filename* may be used to customize the name of the files corresponding to
this field. The field name is used by default.
"""
def __init__(self, storage=None, load=None, dump=None, default=None,
filename=None):
self.load = load
self.dump = dump
if storage is None:
self.storage = default_storage()
else:
self.storage = storage
self.default = default
self.filename = filename
def contribute_to_class(self, cls, name):
if self.filename is not None:
filename = self.filename
else:
filename = name
descriptor = FileStorageFieldDescriptor(filename, self.storage,
self.default, self.load, self.dump)
setattr(cls, name, descriptor)