Examples#
Complete examples of using GraphQL DB.
Blog API#
A complete blog API with posts, users, and comments:
from datetime import datetime
from graphql_api import GraphQLAPI
from graphql_db.orm_base import DatabaseManager, ModelBase
from sqlalchemy import String, Text, DateTime, ForeignKey, Boolean
from sqlalchemy.orm import Mapped, mapped_column, relationship
# Database setup
db_manager = DatabaseManager(url="sqlite:///blog.db")
# Models
class User(ModelBase):
__tablename__ = 'users'
name: Mapped[str] = mapped_column(String(100))
email: Mapped[str] = mapped_column(String(100), unique=True)
posts = relationship("Post", back_populates="author")
class Post(ModelBase):
__tablename__ = 'posts'
title: Mapped[str] = mapped_column(String(200))
content: Mapped[str] = mapped_column(Text)
published: Mapped[bool] = mapped_column(Boolean, default=False)
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
author_id: Mapped[uuid.UUID] = mapped_column(ForeignKey('users.id'))
author = relationship("User", back_populates="posts")
db_manager.create_all()
# GraphQL API
api = GraphQLAPI()
@api.type(is_root_type=True)
class Root:
@api.field
def users(self) -> list[User]:
from sqlalchemy.orm import selectinload
return User.query().options(selectinload(User.posts)).all()
@api.field
def posts(self, published_only: bool = False) -> list[Post]:
from sqlalchemy.orm import selectinload
query = Post.query().options(selectinload(Post.author))
if published_only:
query = query.filter(Post.published == True)
return query.all()
@api.field(mutable=True)
def create_user(self, name: str, email: str) -> User:
user = User(name=name, email=email)
user.create()
return user
@api.field(mutable=True)
def create_post(self, title: str, content: str, author_id: str) -> Post:
import uuid
post = Post(
title=title,
content=content,
author_id=uuid.UUID(author_id)
)
post.create()
return postWith HTTP Server#
Serve the blog API over HTTP using graphql-http:
from graphql_http import GraphQLHTTP
server = GraphQLHTTP.from_api(api)
# Add database session middleware
@server.app.middleware("http")
async def db_session_middleware(request, call_next):
def handler():
return call_next(request)
return await db_manager.with_db_session(handler)()
if __name__ == "__main__":
server.run(host="0.0.0.0", port=8000)With Pagination#
Add Relay-style pagination:
from graphql_db.relay_base import relay_connection
PostConnection = relay_connection(Post)
@api.field
def posts_connection(
self,
first: int | None = 10,
after: str | None = None
) -> PostConnection:
from sqlalchemy.orm import selectinload
query = Post.query().options(selectinload(Post.author))
return PostConnection(
model=Post,
first=first,
after=after,
base_query=query
)Testing#
Test your database API:
import pytest
from graphql_db.orm_base import DatabaseManager
@pytest.fixture
def db():
db_manager = DatabaseManager(url="sqlite:///:memory:", wipe=True)
db_manager.create_all()
return db_manager
def test_create_user(db):
def test_logic():
# Create user via mutation
result = api.execute('''
mutation {
createUser(name: "Test User", email: "test@example.com") {
id
name
email
}
}
''')
assert not result.errors
assert result.data['createUser']['name'] == "Test User"
# Query user
result = api.execute('''
query {
users {
name
email
}
}
''')
assert len(result.data['users']) == 1
assert result.data['users'][0]['name'] == "Test User"
db.with_db_session(test_logic)()More Examples#
See the test suite in the repository for comprehensive examples:
- CRUD Operations: Basic create, read, update, delete
- Relationships: One-to-many and many-to-many
- Pagination: Relay-style cursors
- Performance: Query optimization
For general GraphQL patterns, see the graphql-api examples.