Skip to main content

This fork is a heavily modified version of strawberry-sqlalchemy-mapper with the following additions/changes:

  • Implements relay pagination (using this sqlakeyset fork)
  • Fully async
  • Uses SQLAlchmy 2.0 style
  • Pydantic integration (generated types can also be pydantic models)

strawberry-sqlalchemy-mapper

Strawberry-sqlalchemy-mapper is the simplest way to implement autogenerated strawberry types for columns and relationships in SQLAlchemy models.

  • Instead of manually listing every column and relationship in a SQLAlchemy model, strawberry-sqlalchemy-mapper lets you decorate a class declaration and it will automatically generate the necessary strawberry fields for all columns and relationships (subject to the limitations below) in the given model.

  • Native support for most of SQLAlchemy's most common types.

  • Extensible to arbitrary custom SQLAlchemy types.

  • Automatic batching of queries, avoiding N+1 queries when getting relationships

  • Support for SQLAlchemy >=1.4.x

  • Lightweight and fast.

Getting Started

strawberry-sqlalchemy-mapper is available on PyPi

pip install strawberry-sqlalchemy-mapper

First, define your sqlalchemy model:

# models.py
from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Employee(Base):
    __tablename__ = 'employee'
    id = Column(UUID, primary_key=True)
    name = Column(String, nullable=False)
    password_hash = Column(String, nullable=False)
    department_id = Column(UUID, ForeignKey('department.id'))
    department = relationship('Department', back_populates='employees')

class Department(Base):
    __tablename__ = "department"
    id = Column(UUID, primary_key=True)
    name = Column(String, nullable=False)
    employees = relationship('Employee', back_populates='department')

Next, decorate a type with strawberry_sqlalchemy_mapper.type() to register it as a strawberry type for the given SQLAlchemy model. This will automatically add fields for the model's columns, relationships, association proxies, and hybrid properties. For example:

# elsewhere
# ...
from strawberry_sqlalchemy_mapper import StrawberrySQLAlchemyMapper

strawberry_sqlalchemy_mapper = StrawberrySQLAlchemyMapper()
@strawberry_sqlalchemy_mapper.type(models.Employee)
class Employee:
    __exclude__ = ["password_hash"]


@strawberry_sqlalchemy_mapper.type(models.Department)
class Department:
    pass

@strawberry.type
class Query:
    @strawberry.field
    def departments(self):
        return db.session.scalars(select(models.Department)).all()


# context is expected to have an instance of StrawberrySQLAlchemyLoader
class CustomGraphQLView(GraphQLView):
    def get_context(self):
        return {
            "sqlalchemy_loader": StrawberrySQLAlchemyLoader(bind=YOUR_SESSION),
        }

# call finalize() before using the schema:
# (note that models that are related to models that are in the schema
# are automatically mapped at this stage -- e.g., Department is mapped
# because employee.department is a relationshp to Department)
strawberry_sqlalchemy_mapper.finalize()
# only needed if you have polymorphic types
additional_types = list(strawberry_sqlalchemy_mapper.mapped_types.values())
schema = strawberry.Schema(
    query=Query,
    mutation=Mutation,
    extensions=extensions,
    types=additional_types,
)

# You can now query, e.g.:
"""
query {
    departments {
        id
        name
        employees {
            edge {
                node {
                    id
                    name
                    department {
                        # Just an example of nested relationships
                        id
                        name
                    }
                }
            }
        }
    }
}
"""

Limitations

SQLAlchemy Models -> Strawberry Types and Interfaces are expected to have a consistent (customizable) naming convention. These can be configured by passing model_to_type_name and model_to_interface_name when constructing the mapper.

Natively supports the following SQLAlchemy types:

Integer: int,
Float: float,
BigInteger: int,
Numeric: Decimal,
DateTime: datetime,
Date: date,
Time: time,
String: str,
Text: str,
Boolean: bool,
Unicode: str,
UnicodeText: str,
SmallInteger: int,
SQLAlchemyUUID: uuid.UUID,
VARCHAR: str,
ARRAY[T]: List[T] # PostgreSQL array
Enum: (the Python enum it is mapped to, which should be @strawberry.enum-decorated)

Additional types can be supported by passing extra_sqlalchemy_type_to_strawberry_type_map, although support for TypeDecorator types is untested.

Association proxies are expected to be of the form association_proxy('relationship1', 'relationship2'), i.e., both properties are expected to be relationships.

Roots of polymorphic hierarchies are supported, but are also expected to be registered via strawberry_sqlalchemy_mapper.interface(), and its concrete type and its descendants are expected to inherit from the interface:

class Book(Model):
    id = Column(UUID, primary_key=True)

class Novel(Book):
    pass

class ShortStory(Book):
    pass


# in another file
strawberry_sqlalchemy_mapper = StrawberrySQLAlchemyMapper()

@strawberry_sqlalchemy_mapper.interface(models.Book)
class BookInterface:
    pass

@strawberry_sqlalchemy_mapper.type(models.Book)
class Book:
    pass

@strawberry_sqlalchemy_mapper.type(models.Novel)
class Novel:
    pass

@strawberry_sqlalchemy_mapper.type(models.ShortStory)
class ShortStory:
    pass

Contributing

We encourage you to contribute to strawberry-sqlalchemy-mapper! Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature)
  3. Commit your Changes (git commit -m 'Add some feature')
  4. Push to the Branch (git push origin feature)
  5. Open a Pull Request

Prerequisites

This project uses pre-commit_, please make sure to install it before making any changes::

pip install pre-commit
cd strawberry-sqlalchemy-mapper
pre-commit install

It is a good idea to update the hooks to the latest version::

pre-commit autoupdate

Don't forget to tell your contributors to also install and use pre-commit.

Installation

pip install -r requirements.txt

Test

pytest

⚖️ LICENSE

MIT © strawberry-sqlalchemy-mapper

Metadata

Release files for aio-strawberry-sqlalchemy-mapper 0.8.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for aio-strawberry-sqlalchemy-mapper 0.8.1
File Size Uploaded
aio-strawberry-sqlalchemy-mapper-0.8.1.tar.gz 29.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for aio-strawberry-sqlalchemy-mapper 0.8.1
File Interpreter ABI Platform
aio_strawberry_sqlalchemy_mapper-0.8.1-py3-none-any.whl Python 3 none any Details

Total release size: 60.8 kB

Release files / aio-strawberry-sqlalchemy-mapper-0.8.1.tar.gz

Download URL aio-strawberry-sqlalchemy-mapper-0.8.1.tar.gz
Size 29.9 kB
Tags Source
SHA-256 checksum
How to use checksums
3bb7b8a42d9873d96d09a76ef00b670845a1dec5f26324109159e8bbef4342a2
BLAKE2b-256 checksum
How to use checksums
d72c6f515f2bf5762d77f5810236791f878c69c37518ead6ffbb2bd00d36a888
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.1 CPython/3.8.13

Release files / aio_strawberry_sqlalchemy_mapper-0.8.1-py3-none-any.whl

Download URL aio_strawberry_sqlalchemy_mapper-0.8.1-py3-none-any.whl
Size 30.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
abb5722588a567ec1b2631e3b1bfdbd6e17fc7e11e899fa7448961eca6d3e7ba
BLAKE2b-256 checksum
How to use checksums
133683dd6d2ff8c297e3f3e4a06e130cbac8da6f906c9889a40a3a151430d512
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.1 CPython/3.8.13

Release history Release notifications | RSS feed

This release

0.8.1 This release

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page