@@ -199,125 +199,125 @@ def clean(self, value, model_instance, skip_validation=False):
199
199
"""Clean the value to ensure correct state and on_commit hooks.
200
200
This method is called during clean_fields on model save.
201
201
"""
202
- if not skip_validation and not self ._validated :
203
- self .validate (value , model_instance )
204
202
205
- try :
206
- # Cross-field validation: ensure value is not greater than another field
207
- add = model_instance ._state .adding
203
+ # An escape hatch allowing you to set the path directly. This is dangerous and should only be done
204
+ # explicitly for the purpose of data migration and manipulation. You should never allow an untrusted
205
+ # client to set paths directly, because knowing the path of a pre-existing object allows you to assume
206
+ # access to it. Tip: You can use django's override_settings context manager to set this temporarily.
207
+ if getattr (
208
+ settings ,
209
+ "GCP_STORAGE_OVERRIDE_BLOBFIELD_VALUE" ,
210
+ DEFAULT_OVERRIDE_BLOBFIELD_VALUE ,
211
+ ):
212
+ logger .warning (
213
+ "Overriding %s value to %s" ,
214
+ self .__class__ .__name__ ,
215
+ value ,
216
+ )
217
+ new_value = value
218
+
219
+ else :
220
+ # Validate the value given
221
+ if not skip_validation and not self ._validated :
222
+ self .validate (value , model_instance )
208
223
224
+ # Clean {} --> None
209
225
value = self ._clean_blank_value (getattr (model_instance , self .attname ))
210
226
227
+ # Get model state
228
+ add = model_instance ._state .adding
211
229
existing_path = None if add else self ._get_existing_path (model_instance )
212
230
213
- # An escape hatch allowing you to set the path directly. This is dangerous and should only be done
214
- # explicitly for the purpose of data migration and manipulation. You should never allow an untrusted
215
- # client to set paths directly, because knowing the path of a pre-existing object allows you to assume
216
- # access to it. Tip: You can use django's override_settings context manager to set this temporarily.
217
- if getattr (
218
- settings ,
219
- "GCP_STORAGE_OVERRIDE_BLOBFIELD_VALUE" ,
220
- DEFAULT_OVERRIDE_BLOBFIELD_VALUE ,
221
- ):
222
- logger .warning (
223
- "Overriding %s value to %s" ,
224
- self .__class__ .__name__ ,
225
- value ,
231
+ # There are six scenarios to deal with:
232
+ adding_blank = add and value is None
233
+ adding_valid = add and value is not None
234
+ updating_valid_to_valid = not add and self ._get_valid_to_valid (model_instance )
235
+ updating_valid_to_blank = not add and self ._get_valid_to_blank (model_instance )
236
+ updating_blank_to_valid = not add and self ._get_blank_to_valid (model_instance )
237
+ unchanged = not add and self ._get_unchanged (model_instance )
238
+
239
+ # Branch based on scenarios
240
+ if unchanged :
241
+ new_value = {"path" : value ["path" ]} if value is not None else None
242
+
243
+ elif adding_blank or updating_valid_to_blank :
244
+ new_value = None
245
+
246
+ # Trigger the on_change callback at the end of the commit when we know the
247
+ # database transaction will work
248
+ def on_commit_blank ():
249
+ if self .on_change is not None :
250
+ self .on_change (new_value , instance = model_instance )
251
+
252
+ # clean may happen outside transations so we must
253
+ # actually register the transaction during pre-save,
254
+ # store the callback here temporarily
255
+ self ._on_commit_blank = on_commit_blank
256
+
257
+ elif adding_valid or updating_blank_to_valid or updating_valid_to_valid :
258
+ new_value = {}
259
+
260
+ allow_overwrite = self ._get_allow_overwrite (add )
261
+
262
+ attributes = self ._update_attributes (
263
+ getattr (value , "attributes" , {}),
264
+ instance = model_instance ,
265
+ original_name = value ["name" ],
266
+ existing_path = existing_path ,
267
+ temporary_path = value ["_tmp_path" ],
268
+ adding = add ,
269
+ bucket = self .storage .bucket ,
226
270
)
227
- new_value = value
228
- else :
229
- # There are six scenarios to deal with:
230
- adding_blank = add and value is None
231
- adding_valid = add and value is not None
232
- updating_valid_to_valid = not add and self ._get_valid_to_valid (model_instance )
233
- updating_valid_to_blank = not add and self ._get_valid_to_blank (model_instance )
234
- updating_blank_to_valid = not add and self ._get_blank_to_valid (model_instance )
235
- unchanged = not add and self ._get_unchanged (model_instance )
236
-
237
- if unchanged :
238
- new_value = {"path" : value ["path" ]} if value is not None else None
239
-
240
- elif adding_blank or updating_valid_to_blank :
241
- new_value = None
242
-
243
- # Trigger the on_change callback at the end of the commit when we know the
244
- # database transaction will work
245
- def on_commit_blank ():
246
- if self .on_change is not None :
247
- self .on_change (new_value , instance = model_instance )
248
-
249
- # clean may happen outside transations so we must
250
- # actually register the transaction during pre-save,
251
- # store the callback here temporarily
252
- self ._on_commit_blank = on_commit_blank
253
-
254
- elif adding_valid or updating_blank_to_valid or updating_valid_to_valid :
255
- new_value = {}
256
-
257
- allow_overwrite = self ._get_allow_overwrite (add )
258
-
259
- attributes = self ._update_attributes (
260
- getattr (value , "attributes" , {}),
261
- instance = model_instance ,
262
- original_name = value ["name" ],
263
- existing_path = existing_path ,
264
- temporary_path = value ["_tmp_path" ],
265
- adding = add ,
266
- bucket = self .storage .bucket ,
267
- )
268
271
269
- new_value ["path" ], allow_overwrite = self ._get_destination_path (
270
- instance = model_instance ,
271
- original_name = value ["name" ],
272
- attributes = attributes ,
273
- allow_overwrite = self ._get_allow_overwrite (add ),
274
- existing_path = existing_path ,
275
- temporary_path = value ["_tmp_path" ],
276
- bucket = self .storage .bucket ,
277
- )
272
+ new_value ["path" ], allow_overwrite = self ._get_destination_path (
273
+ instance = model_instance ,
274
+ original_name = value ["name" ],
275
+ attributes = attributes ,
276
+ allow_overwrite = self ._get_allow_overwrite (add ),
277
+ existing_path = existing_path ,
278
+ temporary_path = value ["_tmp_path" ],
279
+ bucket = self .storage .bucket ,
280
+ )
278
281
279
- logger .info (
280
- "Adding/updating cloud object via temporary ingress at %s to %s" ,
281
- value ["_tmp_path" ],
282
- new_value ["path" ],
283
- )
282
+ logger .info (
283
+ "Adding/updating cloud object via temporary ingress at %s to %s" ,
284
+ value ["_tmp_path" ],
285
+ new_value ["path" ],
286
+ )
284
287
285
- # Trigger the copy only on successful commit of the transaction. We have to
286
- # capture the dual edge cases of the file not moving correctly, and the database
287
- # row not saving (eg due to validation errors in other model fields).
288
- # https://stackoverflow.com/questions/33180727/trigering-post-save-signal-only-after-transaction-has-completed
289
- def on_commit_valid ():
290
- copy_blob (
291
- self .storage .bucket ,
292
- value ["_tmp_path" ],
293
- self .storage .bucket ,
294
- new_value ["path" ],
295
- move = True ,
296
- overwrite = allow_overwrite ,
297
- attributes = attributes ,
298
- )
299
- if self .on_change is not None :
300
- self .on_change (new_value , instance = model_instance )
301
-
302
- logger .info (
303
- "Registered move of %s to %s to happen on transaction commit" ,
288
+ # Trigger the copy only on successful commit of the transaction. We have to
289
+ # capture the dual edge cases of the file not moving correctly, and the database
290
+ # row not saving (eg due to validation errors in other model fields).
291
+ # https://stackoverflow.com/questions/33180727/trigering-post-save-signal-only-after-transaction-has-completed
292
+ def on_commit_valid ():
293
+ copy_blob (
294
+ self .storage .bucket ,
304
295
value ["_tmp_path" ],
296
+ self .storage .bucket ,
305
297
new_value ["path" ],
298
+ move = True ,
299
+ overwrite = allow_overwrite ,
300
+ attributes = attributes ,
306
301
)
307
- self ._on_commit_valid = on_commit_valid
302
+ if self .on_change is not None :
303
+ self .on_change (new_value , instance = model_instance )
308
304
309
- else :
310
- # Raise unknown edge cases rather than failing silently
311
- raise ValueError (
312
- f"Unable to determine field state for { self ._get_fieldname (model_instance )} . The most likely cause of this doing an operation (like migration) without setting GCP_STORAGE_OVERRIDE_BLOBFIELD_VALUE=True. Otherwise, please contact the django_gcp developers and describe what you're doing along with this exception stacktrace. Value was: { json .dumps (value )} "
313
- )
305
+ logger .info (
306
+ "Registered move of %s to %s to happen on transaction commit" ,
307
+ value ["_tmp_path" ],
308
+ new_value ["path" ],
309
+ )
310
+ self ._on_commit_valid = on_commit_valid
314
311
315
- # Cache DB values in the instance so you can reuse it without multiple DB queries
316
- # pylint: disable-next=protected-access
317
- model_instance ._state .fields_cache [self .attname ] = new_value
312
+ else :
313
+ # Raise unknown edge cases rather than failing silently
314
+ raise ValueError (
315
+ f"Unable to determine field state for { self ._get_fieldname (model_instance )} . The most likely cause of this doing an operation (like migration) without setting GCP_STORAGE_OVERRIDE_BLOBFIELD_VALUE=True. Otherwise, please contact the django_gcp developers and describe what you're doing along with this exception stacktrace. Value was: { json .dumps (value )} "
316
+ )
318
317
319
- except ValidationError as e :
320
- raise e
318
+ # Cache DB values in the instance so you can reuse it without multiple DB queries
319
+ # pylint: disable-next=protected-access
320
+ model_instance ._state .fields_cache [self .attname ] = new_value
321
321
322
322
self ._cleaned = True
323
323
0 commit comments