{"id":5242,"library":"graphene-sqlalchemy","title":"Graphene SQLAlchemy Integration","description":"Graphene SQLAlchemy integration allows developers to quickly and easily create a GraphQL API that seamlessly interacts with a SQLAlchemy-managed database. It is fully compatible with SQLAlchemy 1.4 and 2.0. The current stable version is 2.3.0, but version 3.0 is in release candidate stage with significant updates, and the project has an active development cadence.","status":"active","version":"2.3.0","language":"en","source_language":"en","source_url":"https://github.com/graphql-python/graphene-sqlalchemy","tags":["graphql","sqlalchemy","orm","graphene","api","database"],"install":[{"cmd":"pip install \"graphene-sqlalchemy\"","lang":"bash","label":"Stable Version"},{"cmd":"pip install --pre \"graphene-sqlalchemy\"","lang":"bash","label":"Pre-release (e.g., v3.0.0rc2)"}],"dependencies":[{"reason":"Core GraphQL library; graphene-sqlalchemy v3.x specifically benefits from graphene>=3.1.1.","package":"graphene"},{"reason":"ORM for database interaction; graphene-sqlalchemy v3.x supports SQLAlchemy 1.4 and 2.0.","package":"SQLAlchemy"},{"reason":"Used for batching in graphene-sqlalchemy v3.x, replacing promises.dataloader for asyncio-dependent queries.","package":"aiodalaloader","optional":true}],"imports":[{"symbol":"SQLAlchemyObjectType","correct":"from graphene_sqlalchemy import SQLAlchemyObjectType"},{"symbol":"SQLAlchemyConnectionField","correct":"from graphene_sqlalchemy import SQLAlchemyConnectionField"}],"quickstart":{"code":"import graphene\nfrom graphene_sqlalchemy import SQLAlchemyObjectType\nfrom sqlalchemy import create_engine, Column, Integer, String\nfrom sqlalchemy.orm import sessionmaker\nfrom sqlalchemy.ext.declarative import declarative_base\n\n# 1. Define SQLAlchemy Model\nBase = declarative_base()\n\nclass UserModel(Base):\n    __tablename__ = 'users'\n    id = Column(Integer, primary_key=True)\n    name = Column(String)\n    email = Column(String, unique=True)\n\n    def __repr__(self):\n        return f\"<User(name='{self.name}', email='{self.email}')>\"\n\n# 2. Configure Database Session\nengine = create_engine('sqlite:///:memory:')\nBase.metadata.create_all(engine)\nSession = sessionmaker(bind=engine)\nsession = Session()\n\n# Add some initial data\nuser1 = UserModel(name='Alice', email='alice@example.com')\nuser2 = UserModel(name='Bob', email='bob@example.com')\nsession.add_all([user1, user2])\nsession.commit()\n\n# 3. Create Graphene Object Type from SQLAlchemy Model\nclass User(SQLAlchemyObjectType):\n    class Meta:\n        model = UserModel\n        interfaces = (graphene.relay.Node,)\n        # Optionally expose specific fields or exclude some\n        # only_fields = (\"name\", \"email\")\n        # exclude_fields = (\"id\",)\n\n# 4. Define Query Type\nclass Query(graphene.ObjectType):\n    node = graphene.relay.Node.Field()\n    all_users = graphene.List(User)\n    user_by_name = graphene.Field(User, name=graphene.String(required=True))\n\n    def resolve_all_users(self, info):\n        # Graphene-SQLAlchemy provides get_query to construct a query\n        # for the model associated with the SQLAlchemyObjectType\n        query = User.get_query(info)\n        return query.all()\n\n    def resolve_user_by_name(self, info, name):\n        query = User.get_query(info)\n        return query.filter(UserModel.name == name).first()\n\n# 5. Create Schema\nschema = graphene.Schema(query=Query)\n\n# 6. Execute a Query\nquery = '''\n    query {\n        allUsers {\n            name\n            email\n        }\n        userByName(name: \"Alice\") {\n            name\n            email\n        }\n    }\n'''\nresult = schema.execute(query, context_value={'session': session})\n\nprint(result.data)\n# Expected output might look like:\n# {'allUsers': [{'name': 'Alice', 'email': 'alice@example.com'}, {'name': 'Bob', 'email': 'bob@example.com'}], 'userByName': {'name': 'Alice', 'email': 'alice@example.com'}}","lang":"python","description":"This quickstart demonstrates how to define a SQLAlchemy model, create a `SQLAlchemyObjectType` from it, and then build a Graphene schema that can query the data. It's crucial to provide an active SQLAlchemy session to the GraphQL execution context for resolvers to function correctly."},"warnings":[{"fix":"Upgrade Python to 3.9+ before upgrading `graphene-sqlalchemy` to v3.x.","message":"Version 3.x of `graphene-sqlalchemy` drops support for Python 3.7 and 3.8, requiring Python 3.9 or newer. Users upgrading to v3.x must ensure their Python environment meets this requirement.","severity":"breaking","affected_versions":"3.x.x"},{"fix":"Review and update DataLoader implementations to use `aiodalaloader` and ensure asynchronous handling for batched queries. Consult the v3.x upgrade guide for detailed changes.","message":"Version 3.x introduces full compatibility with SQLAlchemy 2.0 and replaces the internal `promises.dataloader` with `aiodalaloader`. This makes batched queries asyncio-dependent, requiring applications to adapt to the new asynchronous DataLoader implementation.","severity":"breaking","affected_versions":"3.x.x"},{"fix":"Explicitly define the Graphene type for `hybrid_property` fields in your `SQLAlchemyObjectType` `Meta` class or by adding type hints to the `hybrid_property` method if relying on automatic detection.","message":"In version 3.x, `graphene-sqlalchemy` introduces automatic type detection for SQLAlchemy `hybrid_property` methods based on Python type hints. Previously, these were often implicitly converted to `String` in the GraphQL schema unless explicitly overridden. This change may lead to unexpected GraphQL schema type changes for `hybrid_property` fields.","severity":"breaking","affected_versions":"3.x.x"},{"fix":"Refactor custom filters to align with the new built-in filtering capabilities in `graphene-sqlalchemy` v3.x.","message":"Version 3.x overhauls the filtering syntax, incorporating new filters directly and removing the need for external filtering plugins. This means existing custom filtering logic or reliance on `graphene-sqlalchemy-filter` will likely break.","severity":"breaking","affected_versions":"3.x.x"},{"fix":"Always pass an active SQLAlchemy session via the `context_value` argument when executing a Graphene schema (e.g., `schema.execute(query, context_value={'session': db_session})`). Alternatively, for declarative models, `Base.query = db_session.query_property()` can set a default query property.","message":"A SQLAlchemy session is critical for `graphene-sqlalchemy` to resolve models and execute queries. Forgetting to provide a session to the GraphQL execution context will result in errors.","severity":"gotcha","affected_versions":"All"}],"env_vars":null,"last_verified":"2026-04-13T00:00:00.000Z","next_check":"2026-07-12T00:00:00.000Z"}