@@ -402,26 +402,35 @@ def __repr__(self) -> str:
402402 msg = "{}<{}>" .format (self .Meta .table_name , hash_key )
403403 return msg
404404
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 :
406407 """
407- Deletes this object from dynamodb
408+ Deletes this object from DynamoDB.
408409
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.
409413 :raises pynamodb.exceptions.DeleteError: If the record can not be deleted
410414 """
411415 hk_value , rk_value = self ._get_hash_range_key_serialized_values ()
416+
412417 version_condition = self ._handle_version_attribute ()
413- if version_condition is not None :
418+ if add_version_condition and version_condition is not None :
414419 condition &= version_condition
415420
416421 return self ._get_connection ().delete_item (hk_value , range_key = rk_value , condition = condition , settings = settings )
417422
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 :
419424 """
420425 Updates an item using the UpdateItem operation.
421426
422427 :param actions: a list of Action updates to apply
423428 :param condition: an optional Condition on which to update
424429 :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.
425434 :raises ModelInstance.DoesNotExist: if the object to be updated does not exist
426435 :raises pynamodb.exceptions.UpdateError: if the `condition` is not met
427436 """
@@ -430,7 +439,7 @@ def update(self, actions: List[Action], condition: Optional[Condition] = None, s
430439
431440 hk_value , rk_value = self ._get_hash_range_key_serialized_values ()
432441 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 :
434443 condition &= version_condition
435444
436445 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
441450 self .deserialize (item_data )
442451 return data
443452
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 ]:
445454 """
446455 Save this object to dynamodb
447456 """
448- args , kwargs = self ._get_save_args (condition = condition )
457+ args , kwargs = self ._get_save_args (condition = condition , add_version_condition = add_version_condition )
449458 kwargs ['settings' ] = settings
450459 data = self ._get_connection ().put_item (* args , ** kwargs )
451460 self .update_local_version_attribute ()
@@ -474,11 +483,13 @@ def get_update_kwargs_from_instance(
474483 actions : List [Action ],
475484 condition : Optional [Condition ] = None ,
476485 return_values_on_condition_failure : Optional [str ] = None ,
486+ * ,
487+ add_version_condition : bool = True ,
477488 ) -> Dict [str , Any ]:
478489 hk_value , rk_value = self ._get_hash_range_key_serialized_values ()
479490
480491 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 :
482493 condition &= version_condition
483494
484495 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(
487498 self ,
488499 condition : Optional [Condition ] = None ,
489500 return_values_on_condition_failure : Optional [str ] = None ,
501+ * ,
502+ add_version_condition : bool = True ,
490503 ) -> Dict [str , Any ]:
491504 hk_value , rk_value = self ._get_hash_range_key_serialized_values ()
492505
493506 version_condition = self ._handle_version_attribute ()
494- if version_condition is not None :
507+ if add_version_condition and version_condition is not None :
495508 condition &= version_condition
496509
497510 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]:
900913 })
901914 return schema
902915
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 ]]:
904917 """
905918 Gets the proper *args, **kwargs for saving and retrieving this object
906919
907920 This is used for serializing items to be saved, or for serializing just the keys.
908921
909922 :param null_check: If True, then attributes are checked for null.
910923 :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.
911927 """
912928 attribute_values = self .serialize (null_check )
913929 hash_key_attribute = self ._hash_key_attribute ()
@@ -921,7 +937,7 @@ def _get_save_args(self, null_check: bool = True, condition: Optional[Condition]
921937 if range_key is not None :
922938 kwargs ['range_key' ] = range_key
923939 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 :
925941 condition &= version_condition
926942 kwargs ['attributes' ] = attribute_values
927943 kwargs ['condition' ] = condition
0 commit comments