@@ -402,26 +402,35 @@ def __repr__(self) -> str:
402
402
msg = "{}<{}>" .format (self .Meta .table_name , hash_key )
403
403
return msg
404
404
405
- def delete (self , condition : Optional [Condition ] = None , settings : OperationSettings = OperationSettings .default ) -> Any :
405
+ def delete (self , condition : Optional [Condition ] = None , settings : OperationSettings = OperationSettings .default ,
406
+ * , add_version_condition : bool = True ) -> Any :
406
407
"""
407
- Deletes this object from dynamodb
408
+ Deletes this object from DynamoDB.
408
409
410
+ :param add_version_condition: For models which have a :class:`~pynamodb.attributes.VersionAttribute`,
411
+ specifies whether the item should only be deleted if its current version matches the expected one.
412
+ Set to `False` for a 'delete anyway' strategy.
409
413
:raises pynamodb.exceptions.DeleteError: If the record can not be deleted
410
414
"""
411
415
hk_value , rk_value = self ._get_hash_range_key_serialized_values ()
416
+
412
417
version_condition = self ._handle_version_attribute ()
413
- if version_condition is not None :
418
+ if add_version_condition and version_condition is not None :
414
419
condition &= version_condition
415
420
416
421
return self ._get_connection ().delete_item (hk_value , range_key = rk_value , condition = condition , settings = settings )
417
422
418
- def update (self , actions : List [Action ], condition : Optional [Condition ] = None , settings : OperationSettings = OperationSettings .default ) -> Any :
423
+ def update (self , actions : List [Action ], condition : Optional [Condition ] = None , settings : OperationSettings = OperationSettings .default , * , add_version_condition : bool = True ) -> Any :
419
424
"""
420
425
Updates an item using the UpdateItem operation.
421
426
422
427
:param actions: a list of Action updates to apply
423
428
:param condition: an optional Condition on which to update
424
429
:param settings: per-operation settings
430
+ :param add_version_condition: For models which have a :class:`~pynamodb.attributes.VersionAttribute`,
431
+ specifies whether only to update if the version matches the model that is currently loaded.
432
+ Set to `False` for a 'last write wins' strategy.
433
+ Regardless, the version will always be incremented to prevent "rollbacks" by concurrent :meth:`save` calls.
425
434
:raises ModelInstance.DoesNotExist: if the object to be updated does not exist
426
435
:raises pynamodb.exceptions.UpdateError: if the `condition` is not met
427
436
"""
@@ -430,7 +439,7 @@ def update(self, actions: List[Action], condition: Optional[Condition] = None, s
430
439
431
440
hk_value , rk_value = self ._get_hash_range_key_serialized_values ()
432
441
version_condition = self ._handle_version_attribute (actions = actions )
433
- if version_condition is not None :
442
+ if add_version_condition and version_condition is not None :
434
443
condition &= version_condition
435
444
436
445
data = self ._get_connection ().update_item (hk_value , range_key = rk_value , return_values = ALL_NEW , condition = condition , actions = actions , settings = settings )
@@ -441,11 +450,11 @@ def update(self, actions: List[Action], condition: Optional[Condition] = None, s
441
450
self .deserialize (item_data )
442
451
return data
443
452
444
- def save (self , condition : Optional [Condition ] = None , settings : OperationSettings = OperationSettings .default ) -> Dict [str , Any ]:
453
+ def save (self , condition : Optional [Condition ] = None , settings : OperationSettings = OperationSettings .default , * , add_version_condition : bool = True ) -> Dict [str , Any ]:
445
454
"""
446
455
Save this object to dynamodb
447
456
"""
448
- args , kwargs = self ._get_save_args (condition = condition )
457
+ args , kwargs = self ._get_save_args (condition = condition , add_version_condition = add_version_condition )
449
458
kwargs ['settings' ] = settings
450
459
data = self ._get_connection ().put_item (* args , ** kwargs )
451
460
self .update_local_version_attribute ()
@@ -474,11 +483,13 @@ def get_update_kwargs_from_instance(
474
483
actions : List [Action ],
475
484
condition : Optional [Condition ] = None ,
476
485
return_values_on_condition_failure : Optional [str ] = None ,
486
+ * ,
487
+ add_version_condition : bool = True ,
477
488
) -> Dict [str , Any ]:
478
489
hk_value , rk_value = self ._get_hash_range_key_serialized_values ()
479
490
480
491
version_condition = self ._handle_version_attribute (actions = actions )
481
- if version_condition is not None :
492
+ if add_version_condition and version_condition is not None :
482
493
condition &= version_condition
483
494
484
495
return self ._get_connection ().get_operation_kwargs (hk_value , range_key = rk_value , key = KEY , actions = actions , condition = condition , return_values_on_condition_failure = return_values_on_condition_failure )
@@ -487,11 +498,13 @@ def get_delete_kwargs_from_instance(
487
498
self ,
488
499
condition : Optional [Condition ] = None ,
489
500
return_values_on_condition_failure : Optional [str ] = None ,
501
+ * ,
502
+ add_version_condition : bool = True ,
490
503
) -> Dict [str , Any ]:
491
504
hk_value , rk_value = self ._get_hash_range_key_serialized_values ()
492
505
493
506
version_condition = self ._handle_version_attribute ()
494
- if version_condition is not None :
507
+ if add_version_condition and version_condition is not None :
495
508
condition &= version_condition
496
509
497
510
return self ._get_connection ().get_operation_kwargs (hk_value , range_key = rk_value , key = KEY , condition = condition , return_values_on_condition_failure = return_values_on_condition_failure )
@@ -900,14 +913,17 @@ def _get_schema(cls) -> Dict[str, Any]:
900
913
})
901
914
return schema
902
915
903
- def _get_save_args (self , null_check : bool = True , condition : Optional [Condition ] = None ) -> Tuple [Iterable [Any ], Dict [str , Any ]]:
916
+ def _get_save_args (self , null_check : bool = True , condition : Optional [Condition ] = None , * , add_version_condition : bool = True ) -> Tuple [Iterable [Any ], Dict [str , Any ]]:
904
917
"""
905
918
Gets the proper *args, **kwargs for saving and retrieving this object
906
919
907
920
This is used for serializing items to be saved, or for serializing just the keys.
908
921
909
922
:param null_check: If True, then attributes are checked for null.
910
923
:param condition: If set, a condition
924
+ :param add_version_condition: For models which have a :class:`~pynamodb.attributes.VersionAttribute`,
925
+ specifies whether the item should only be saved if its current version matches the expected one.
926
+ Set to `False` for a 'last-write-wins' strategy.
911
927
"""
912
928
attribute_values = self .serialize (null_check )
913
929
hash_key_attribute = self ._hash_key_attribute ()
@@ -921,7 +937,7 @@ def _get_save_args(self, null_check: bool = True, condition: Optional[Condition]
921
937
if range_key is not None :
922
938
kwargs ['range_key' ] = range_key
923
939
version_condition = self ._handle_version_attribute (attributes = attribute_values )
924
- if version_condition is not None :
940
+ if add_version_condition and version_condition is not None :
925
941
condition &= version_condition
926
942
kwargs ['attributes' ] = attribute_values
927
943
kwargs ['condition' ] = condition
0 commit comments