{"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":"python","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,"search_vec":"'6.1.0':33 'abstract':11 'activ':37 'amazon':8 'api':20 'aw':19,53 'away':12 'cadenc':39 'chang':52 'current':30 'databas':56 'dynamodb':10,54 'frequent':41 'interact':21 'interfac':6 'introduc':50 'level':18 'like':26 'low':17 'low-level':16 'maintain':35 'major':48 'minor':44 'model':27 'much':13 'nosql':57 'occasion':47 'orm':25,55 'orm-lik':24 'patch':42 'provid':3 'pynamodb':1,2 'python':5 'releas':38,49 'signific':51 'updat':45 'version':32","created_at":"2026-04-09T03:57:24.113141+00:00","updated_at":"2026-04-16T18:34:42.754956+00:00","problems":[{"fix":"Ensure all primary key attributes (hash and range key) are provided for get operations. For secondary indexes, use query instead of get_item, and ensure the query uses the index's defined keys.","cause":"This error occurs when a get or query operation is attempted with an incomplete or incorrect primary key (hash key and range key if defined), or when trying to use get_item on a secondary index, which is not supported.","error":"ValidationException: The provided key element does not match the schema."},{"fix":"Handle the ConditionalCheckFailedException by re-fetching the item, applying the desired changes, and retrying the operation. For optimistic locking, this involves re-retrieving the item to get the latest version. If conditional checks are not desired for a specific update, `add_version_condition=False` can be passed to `update` (use with caution).","cause":"This exception is raised during a save(), update(), or delete() operation when a specified condition on the item is not met, often due to optimistic locking where the item's version has changed concurrently.","error":"ConditionalCheckFailedException"},{"fix":"Convert the MapAttribute instance to a Python dictionary using the `.as_dict()` method before JSON serialization.","cause":"PynamoDB's MapAttribute objects are not standard Python dictionaries and thus cannot be directly serialized to JSON by default JSON encoders or frameworks like Flask.","error":"TypeError: Object of type 'MapAttribute' is not JSON serializable"},{"fix":"Ensure that attributes defined with `null=False` always have a non-None value before saving. If an attribute can legitimately be None, define it explicitly with `null=True` in the model definition.","cause":"This occurs when attempting to save a PynamoDB model with a None value for an attribute that was defined with null=False (the default), as PynamoDB prevents None values from being written to DynamoDB for non-nullable attributes. A related error, `TypeError: 'NoneType' object is not iterable`, can also occur if PynamoDB encounters an unexpected None during key schema processing.","error":"AttributeNullError: Raised when an attribute which is not nullable (:code:null=False) is unset during serialization."},{"fix":"Define an inner `Meta` class within your model, and specify the `table_name` attribute. For example: `class MyModel(Model): class Meta: table_name = 'my-table-name'`.","cause":"A PynamoDB Model subclass is missing the required inner Meta class or the table_name attribute within it, which PynamoDB needs to associate the model with a DynamoDB table.","error":"AttributeError: As of v1.0 PynamoDB Models require a `Meta` class with a table_name property."}],"ecosystem":"pypi","meta_description":null,"install_score":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":"6.1.0","cli_name":"","cli_version":null,"type":"library","homepage":"http://jlafon.io/pynamodb.html","github":"https://github.com/pynamodb/PynamoDB","docs":null,"changelog":null,"pypi":"https://pypi.org/project/pynamodb/","npm":null,"openapi_spec":null,"status_page":null,"smithery":null,"categories":["aws","database"],"base_url":null,"auth_type":null,"provenance":{"verified_status":"passing","verified_at":"2026-06-28","last_verified":"2026-08-27","next_check":"2026-07-28","install_tag":null}}