The main thing to remember is that a batch_get call on a table with a hash key and a range (or sort) key requires both keys for the request. If you have a list of hash keys and the range key is constant, you can use map with a lambda to combine them into a list of tuples:

list_of_tuples = list(map(lambda x: (x, "constant-range-key"), hash_key_listlike

PynamoDB and batch_get without a Range Key#

PynamoDB requires a list of dicts when calling batch_get on a model with a hash and range key. If you try calling it with a set or list (which is allowed because not all models will include a range key), then the string hash keys will be interpreted as a tuple of strings, with the first character being interpreted as the hash key and the second one interpreted as a range key.

This could result in head-scratching errors like a duplicate-item error when a set is passed in. This can also happen with BatchWriteItem operations.

Exceptions#

pynamodb.exceptions.PutError: Failed to batch write items: An error occurred (ValidationException) on request ($id) on table ($table) when calling the BatchWriteItem operation: Provided list of item keys contains duplicates

Pynamo Code for Get#

if range_key_attribute:  
    hash_key, range_key = cls._serialize_keys(item[0], item[1])  # type: ignore  
    keys_to_get.append({  
        hash_key_attribute.attr_name: hash_key,  
        range_key_attribute.attr_name: range_key  
    })  
else:  
    hash_key = cls._serialize_keys(item)[0]  
    keys_to_get.append({  
        hash_key_attribute.attr_name: hash_key  
    })

Sources#

  • Using Python Lambdas to construct combination keys
  • Attempting to use is_in to preserve batch_get and failing
  • Why a tuple must always be passed to batch_get on a Pynamo model with hash and range keys