Install & Compatibility
Where this runs
tested against v6.1.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.920 runs
installs and imports cleanly · install 0.0s · import 0.951s · 26.7MB
glibcpy 3.10–3.920 runs
installs and imports cleanly · install 2.3s · import 0.870s · 27MB
25MB installed
● package 25MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
StructuredNode
✓ from neomodel import StructuredNode
StringProperty
✓ from neomodel import StringProperty
IntegerProperty
✓ from neomodel import IntegerProperty
RelationshipTo
✓ from neomodel import RelationshipTo
RelationshipFrom
✓ from neomodel import RelationshipFrom
db
✓ from neomodel import db
config
✓ from neomodel import db
✗ from neomodel import config; config.DATABASE_URL = 'bolt://...'
The `neomodel.config` module was removed in v6.0.0. All configuration, including database connection, is now handled via the `neomodel.db` object.
This quickstart demonstrates how to connect to a Neo4j database, define a `StructuredNode` model with properties and relationships, create and save nodes, establish relationships, and query the graph using neomodel. It uses environment variables for secure connection details.
import os
from neomodel import StructuredNode, StringProperty, IntegerProperty, RelationshipTo, db
# Configure connection to Neo4j
NEO4J_URL = os.environ.get('NEO4J_BOLT_URL', 'bolt://neo4j:password@localhost:7687')
db.set_connection(NEO4J_URL)
# Define a Node model
class Person(StructuredNode):
uid = StringProperty(unique_index=True)
name = StringProperty(index=True, required=True)
age = IntegerProperty(index=True, default=0)
# Define a relationship
friends = RelationshipTo('Person', 'FRIENDS_WITH')
# Ensure labels and constraints are created in the database
Person.ensure_indexes()
# Create and save nodes
jim = Person(uid='jim001', name='Jim', age=32).save()
pam = Person(uid='pam001', name='Pam', age=30).save()
# Create a relationship
jim.friends.connect(pam)
# Retrieve and query
found_jim = Person.nodes.get(uid='jim001')
print(f"Found: {found_jim.name}, Age: {found_jim.age}")
# Get friends
print(f"{found_jim.name} is friends with:")
for friend in found_jim.friends.all():
print(f"- {friend.name}")
# Clear database for example (use with caution in production)
# db.cypher_query("MATCH (n) DETACH DELETE n")
db.close_connection()
Errors
Common errors & fixes
AttributeError: module 'neomodel.config' has no attribute 'DATABASE_URL'
Attempting to set the Neo4j connection URL using the deprecated `neomodel.config` module, which was removed in neomodel v6.0.0.
fixUse `from neomodel import db; db.set_connection('bolt://user:password@host:port')` to configure your database connection. neo4j.exceptions.ServiceUnavailable: Failed to establish connection
The Neo4j database is not running, is inaccessible from the client, or the connection details (URL, username, password) provided to `db.set_connection` are incorrect.
fixVerify that your Neo4j instance is running and accessible. Double-check the connection URL, username, and password passed to `db.set_connection`. Ensure correct firewall rules or network configuration.
TypeError: Object of type <class 'neomodel.relationship.Relationship'> is not JSON serializable
Attempting to directly serialize a `StructuredNode` or `Relationship` object, which are not standard Python dicts and contain complex internal structures that JSON serializers cannot handle by default.
fixBefore serializing, convert neomodel objects into a JSON-friendly format. For nodes, you can often use `node.__properties__` to get a dictionary of its simple properties, or manually select attributes. For relationships, you might need to extract specific properties like `type` or related nodes.
ValueError: No default value for property 'my_required_property' defined
You are trying to create a `StructuredNode` instance without providing a value for a property that is marked `required=True` and does not have a `default` value defined.
fixWhen creating a new node, ensure all `required=True` properties are provided a value, or define a `default` value for them in your model definition (e.g., `my_property = StringProperty(required=True, default='N/A')`).
neomodel.exceptions.ConstraintValidationFailed: Node (X) already exists with label '...' and property '...' = '...'
You are attempting to create a node with a property value (e.g., an `email` address) that is marked `unique_index=True` on your model, but another node with the same value already exists in the database.
fixBefore creating a new node, check if a node with the unique property already exists using `YourModel.nodes.get_or_none(your_unique_prop=value)`. If it exists, retrieve and use it; otherwise, create a new one. Also ensure `YourModel.ensure_indexes()` or `db.install_all_labels()` has been run to create the unique constraint in Neo4j.
Upgrade
Version history
6.1.0latest on PyPI · released Mar 4, 2026
Audit
Dependencies
neo4jrequiredneomodel is an OGM for Neo4j, relying on the official Neo4j Python driver for database communication.
pydanticrequiredUsed internally for data validation and model definition.