23
23
24
24
DEFAULT_OVERWRITE_MODE = "never"
25
25
26
+ OVERWRITE_MODES = [
27
+ "never" ,
28
+ "update" ,
29
+ "update-versioned" ,
30
+ "add" ,
31
+ "add-versioned" ,
32
+ "add-update" ,
33
+ "add-update-versioned" ,
34
+ ]
35
+
26
36
DEFAULT_OVERRIDE_BLOBFIELD_VALUE = False
27
37
28
38
@@ -31,28 +41,23 @@ class BlobField(models.JSONField):
31
41
32
42
Features such as metadata fetching/synchronisation and direct uploads are enabled.
33
43
34
- ObjectField allows storage classes to be declared in settings. This enables:
44
+ BlobField allows storage classes to be declared in settings. This enables:
35
45
- storages to be switched without database migrations (supporting integration
36
46
and release preview type workflows plus cloud migration)
37
- - eaiser way of using different buckets for different ObjectFields without
47
+ - eaiser way of using different buckets for different BlobFields without
38
48
defining a Storage class for each bucket
39
49
40
- ObjectField is built on JSONField to allow more complex information to be stored
50
+ BlobField is built on JSONField to allow more complex information to be stored
41
51
and queried. Examples might include:
42
52
- cached object generation or metageneration,
43
53
- cached object metadata, or
44
54
- status of direct uploads
45
55
46
- ObjectField does not inherit directly from FileField to avoid the burden of strict
56
+ BlobField does not inherit directly from FileField to avoid the burden of strict
47
57
compatibility with legacy or irrelevant-to-cloud-storage behaviour (like django
48
58
admin overriding formfields or coping with edge cases around name and path handling).
49
59
We do this to support a clear and maintainable implementation.
50
60
51
- ObjectField can read FileField entries: since FileField stores the path as a string,
52
- that's valid JSON so can be accepted by ObjectField, greatly simplifying migration.
53
- Once a model instance has been updated, its entry will be a JSON object and so will
54
- no longer be trivially reversible to a valid FileField entry without a custom migration.
55
-
56
61
:param ingress_to: A string defining the path within the bucket to which direct uploads
57
62
will be ingressed, if temporary_ingress=True. These uploaded files will be moved to their
58
63
ultimate path in the store on save of the model.
@@ -61,15 +66,26 @@ class BlobField(models.JSONField):
61
66
specific mimetype. No validation is done at the field level that objects actually are of this
62
67
type (because the python mimetypes module doesn't accept wildcard mimetypes and we don't want to
63
68
go on a wild goose chase just for this small feature).
69
+
64
70
:param get_destination_path: A callable to determine the destination path of the blob.
65
71
The blob should already have been successfully uploaded to the temporary location
66
72
in GCP prior to creation of this model instance. This function is then called in the
67
73
pre_save stage of the new model instance, so it has access to all the model fields in
68
74
order to construct the destination filename. Note this EXCLUDES the id, if the model has an
69
75
autoincrementing ID field that gets created on save, because that can't be known prior to
70
76
the save.
77
+
71
78
:param max_size_bytes: The maximum size in bytes of files that can be uploaded.
72
79
80
+ :overwrite_mode: One of `OVERWRITE_MODES` determining the circumstances under which overwrite
81
+ is allowed. overwrite mode behaves as follows:
82
+ - never: Never allows overwrite
83
+ - update: Only when updating an object
84
+ - update-versioned: Only when updating an object and the bucket has object versioning
85
+ - add: Only when adding an object (we're not sure why you'd want this, here for completeness)
86
+ - add-versioned: Only when adding an object to a versioned bucket (again, for completeness)
87
+ - add-update: Always allow (ie when adding or updating an object)
88
+ - add-update-versioned: When adding or updating an object to a versioned bucket
73
89
"""
74
90
75
91
description = _ ("A GCP Cloud Storage object" )
@@ -170,9 +186,9 @@ def pre_save(self, model_instance, add):
170
186
# access to it. Tip: You can use django's override_settings context manager to set this temporarily.
171
187
if getattr (settings , "GCP_STORAGE_OVERRIDE_BLOBFIELD_VALUE" , DEFAULT_OVERRIDE_BLOBFIELD_VALUE ):
172
188
logger .warning (
173
- "Overriding %s value with path %s" ,
189
+ "Overriding %s value to %s" ,
174
190
self .__class__ .__name__ ,
175
- getattr ( value , "path" , None ) ,
191
+ value ,
176
192
)
177
193
new_value = value
178
194
else :
@@ -358,22 +374,13 @@ def _check_ingress_to(self):
358
374
return []
359
375
360
376
def _check_overwrite_mode (self ):
361
- allowable_modes = [
362
- "never" ,
363
- "update" ,
364
- "update-versioned" ,
365
- "add" ,
366
- "add-versioned" ,
367
- "add-update" ,
368
- "add-update-versioned" ,
369
- ]
370
- if self .overwrite_mode not in allowable_modes :
377
+ if self .overwrite_mode not in OVERWRITE_MODES :
371
378
return [
372
379
checks .Error (
373
380
"{self.__class__.__name__}'s 'overwrite_mode' is invalid" ,
374
381
obj = self ,
375
382
id = "fields.E202" ,
376
- hint = f"Try one of: { allowable_modes } " ,
383
+ hint = f"Try one of: { OVERWRITE_MODES } " ,
377
384
)
378
385
]
379
386
return []
0 commit comments