PynamoDB
PynamoDB provides a Pythonic interface to Amazon's DynamoDB, abstracting away much of the low-level AWS API interaction into an ORM-like model. It is currently at version 6.1.0 and maintains an active release cadence with frequent patch and minor updates, and occasional major releases introducing significant changes.
Warnings
- breaking `Model.get()` now raises `pynamodb.exceptions.DoesNotExist` instead of returning `None` when an item is not found.
- breaking `Model.query()` and `Model.scan()` no longer return lists by default, but iterators. The `query_count` and `scan_count` methods have been removed.
- gotcha PynamoDB frequently encounters compatibility issues with specific `botocore` versions, often requiring users to pin `botocore` or upgrade PynamoDB.
- gotcha When using local DynamoDB, the `host` setting in `Model.Meta` or the `DYNAMODB_HOST` environment variable must be explicitly configured (e.g., `'http://localhost:8000'`).
- deprecated Several internal classes and functions, including `PynamoDBConnection`, `PynamoDBException`, and `PynamoDBVersionError` were removed as part of a cleanup.
Install
-
pip install pynamodb -
pip install pynamodb[json]
Imports
- Model
from pynamodb.models import Model
- Attribute types
from pynamodb.attributes import UnicodeAttribute, NumberAttribute, MapAttribute, ListAttribute, BooleanAttribute
- DoesNotExist
from pynamodb.exceptions import DoesNotExist
- settings
from pynamodb import settings
Quickstart
import os
from pynamodb.models import Model
from pynamodb.attributes import UnicodeAttribute, NumberAttribute
from pynamodb.exceptions import DoesNotExist
# Configure AWS credentials and region via environment variables
# AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION
# For local DynamoDB, set DYNAMODB_HOST, e.g., 'http://localhost:8000'
class Product(Model):
class Meta:
table_name = os.environ.get('PRODUCT_TABLE_NAME', 'dev-products-table')
region = os.environ.get('AWS_REGION', 'us-east-1')
host = os.environ.get('DYNAMODB_HOST', None) # Set for local DynamoDB
# Optional: read_capacity_units and write_capacity_units are needed for new tables
product_id = UnicodeAttribute(hash_key=True)
name = UnicodeAttribute()
price = NumberAttribute(default=0)
description = UnicodeAttribute(null=True)
# Create table if it doesn't exist
if not Product.exists():
print(f"Creating table '{Product.Meta.table_name}'...")
Product.create_table(read_capacity_units=1, write_capacity_units=1, wait=True)
print(f"Table '{Product.Meta.table_name}' created.")
# Create an item
product = Product(product_id='P123', name='Laptop', price=1200.50, description='High-performance laptop')
product.save()
print(f"Product saved: {product.product_id}")
# Get an item
try:
retrieved_product = Product.get('P123')
print(f"Retrieved product: {retrieved_product.name}, Price: {retrieved_product.price}")
except DoesNotExist:
print("Product not found.")
# Update an item
retrieved_product.update(actions=[
Product.price.set(1150.00),
Product.description.set('Updated description for the laptop')
])
print(f"Product updated: {retrieved_product.product_id}, New price: {retrieved_product.price}")
# Delete an item
# retrieved_product.delete()
# print(f"Product {retrieved_product.product_id} deleted.")