{"id":1654,"library":"pynamodb","title":"PynamoDB","description":"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.","status":"active","version":"6.1.0","language":"en","source_language":"en","source_url":"https://github.com/pynamodb/PynamoDB","tags":["aws","dynamodb","orm","database","nosql"],"install":[{"cmd":"pip install pynamodb","lang":"bash","label":"Install PynamoDB"},{"cmd":"pip install pynamodb[json]","lang":"bash","label":"Install with JSON support"}],"dependencies":[{"reason":"Core AWS SDK dependency; frequent compatibility issues across minor versions.","package":"botocore","optional":false}],"imports":[{"symbol":"Model","correct":"from pynamodb.models import Model"},{"symbol":"Attribute types","correct":"from pynamodb.attributes import UnicodeAttribute, NumberAttribute, MapAttribute, ListAttribute, BooleanAttribute"},{"note":"As of v6.0.0, Model.get() raises DoesNotExist instead of returning None.","wrong":"if item is None: # for Model.get() pre-6.0.0","symbol":"DoesNotExist","correct":"from pynamodb.exceptions import DoesNotExist"},{"note":"Used for global configuration, e.g., thread_local_connection.","symbol":"settings","correct":"from pynamodb import settings"}],"quickstart":{"code":"import os\nfrom pynamodb.models import Model\nfrom pynamodb.attributes import UnicodeAttribute, NumberAttribute\nfrom pynamodb.exceptions import DoesNotExist\n\n# Configure AWS credentials and region via environment variables\n# AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION\n# For local DynamoDB, set DYNAMODB_HOST, e.g., 'http://localhost:8000'\n\nclass Product(Model):\n    class Meta:\n        table_name = os.environ.get('PRODUCT_TABLE_NAME', 'dev-products-table')\n        region = os.environ.get('AWS_REGION', 'us-east-1')\n        host = os.environ.get('DYNAMODB_HOST', None) # Set for local DynamoDB\n        # Optional: read_capacity_units and write_capacity_units are needed for new tables\n\n    product_id = UnicodeAttribute(hash_key=True)\n    name = UnicodeAttribute()\n    price = NumberAttribute(default=0)\n    description = UnicodeAttribute(null=True)\n\n# Create table if it doesn't exist\nif not Product.exists():\n    print(f\"Creating table '{Product.Meta.table_name}'...\")\n    Product.create_table(read_capacity_units=1, write_capacity_units=1, wait=True)\n    print(f\"Table '{Product.Meta.table_name}' created.\")\n\n# Create an item\nproduct = Product(product_id='P123', name='Laptop', price=1200.50, description='High-performance laptop')\nproduct.save()\nprint(f\"Product saved: {product.product_id}\")\n\n# Get an item\ntry:\n    retrieved_product = Product.get('P123')\n    print(f\"Retrieved product: {retrieved_product.name}, Price: {retrieved_product.price}\")\nexcept DoesNotExist:\n    print(\"Product not found.\")\n\n# Update an item\nretrieved_product.update(actions=[\n    Product.price.set(1150.00),\n    Product.description.set('Updated description for the laptop')\n])\nprint(f\"Product updated: {retrieved_product.product_id}, New price: {retrieved_product.price}\")\n\n# Delete an item\n# retrieved_product.delete()\n# print(f\"Product {retrieved_product.product_id} deleted.\")","lang":"python","description":"This quickstart demonstrates defining a basic PynamoDB Model, creating its corresponding DynamoDB table (if it doesn't exist), saving a new item, retrieving an item by its hash key, and updating an item. It highlights common configuration options for AWS region and local DynamoDB setup."},"warnings":[{"fix":"Update `Model.get()` calls to wrap them in a `try...except DoesNotExist` block. If `None` return behavior is desired, pass `consistent_read=False` to `get()`.","message":"`Model.get()` now raises `pynamodb.exceptions.DoesNotExist` instead of returning `None` when an item is not found.","severity":"breaking","affected_versions":"6.0.0 and later"},{"fix":"Iterate directly over the results of `query()` or `scan()`. If a list is required, cast the iterator to a list (e.g., `list(Model.query(...))`). Implement custom logic for counting if needed.","message":"`Model.query()` and `Model.scan()` no longer return lists by default, but iterators. The `query_count` and `scan_count` methods have been removed.","severity":"breaking","affected_versions":"6.0.0 and later"},{"fix":"Ensure `botocore` is within the range specified by `pynamodb`'s `install_requires`. If issues arise, check PynamoDB's GitHub releases or issues for known `botocore` incompatibilities and suggested version pins.","message":"PynamoDB frequently encounters compatibility issues with specific `botocore` versions, often requiring users to pin `botocore` or upgrade PynamoDB.","severity":"gotcha","affected_versions":"All versions, historically (e.g., 4.x, 5.x, 6.x)"},{"fix":"Set `host` in `Model.Meta` or ensure the `DYNAMODB_HOST` environment variable is correctly set before initializing models.","message":"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'`).","severity":"gotcha","affected_versions":"All versions"},{"fix":"Migrate to `pynamodb.connection.Connection` and catch more specific exceptions like `pynamodb.exceptions.TableDoesNotExist` or general `botocore.exceptions.ClientError`.","message":"Several internal classes and functions, including `PynamoDBConnection`, `PynamoDBException`, and `PynamoDBVersionError` were removed as part of a cleanup.","severity":"deprecated","affected_versions":"6.0.0 and later"}],"env_vars":null,"last_verified":"2026-04-09T00:00:00.000Z","next_check":"2026-07-08T00:00:00.000Z"}