A FastAPI application implementing CRUD operations for notes using GraphQL and PostgreSQL following SOLID principles.
- FastAPI - Modern, fast web framework for building APIs
- GraphQL - Query language and runtime for APIs
- PostgreSQL - Powerful, open source object-relational database system
- SOLID Principles - Clean architecture with proper separation of concerns
- Type Safety - Full type hints and annotations throughout
- Environment Configuration - Secure configuration management
- Comprehensive Documentation - Detailed docstrings and type annotations
The application follows a clean architecture pattern with clear separation of concerns:
Client Request
β
FastAPI Server (main.py)
β
GraphQL Router
β
Schema (schema.py)
β
Resolvers (queries.py / mutations.py)
β
Services (note_service.py)
β
Repositories (note_repository.py)
β
Database (PostgreSQL)
β
Response to Client
graphql_practices/
βββ app/
β βββ __init__.py
β βββ main.py # FastAPI app entry point
β βββ core/
β β βββ __init__.py
β β βββ config.py # Settings & environment variables
β β βββ database.py # Database connection
β β βββ dependencies.py # Dependency injection
β βββ graphql/
β β βββ __init__.py
β β βββ schema.py # GraphQL schema
β β βββ types.py # GraphQL type definitions
β β βββ queries.py # Query resolvers
β β βββ mutations.py # Mutation resolvers
β βββ models/
β β βββ __init__.py
β β βββ note.py # SQLAlchemy models
β βββ repositories/
β β βββ __init__.py
β β βββ note_repository.py # Data access layer
β βββ services/
β β βββ __init__.py
β β βββ note_service.py # Business logic layer
β βββ schemas/
β βββ __init__.py
β βββ note.py # Pydantic models
βββ .env # Environment variables
βββ .gitignore # Git ignore file
βββ requirements.txt # Python dependencies
βββ README.md # This file
-
Clone the repository
git clone <repository-url> cd graphql_practices
-
Create virtual environment
python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate
-
Install dependencies
pip install -r requirements.txt
-
Setup environment variables
cp .env.example .env # Edit .env with your database configuration -
Setup PostgreSQL database
CREATE DATABASE notes_db; CREATE USER username WITH PASSWORD 'password'; GRANT ALL PRIVILEGES ON DATABASE notes_db TO username;
The application uses environment variables for configuration. Update the .env file:
# Database Configuration
DATABASE_URL=postgresql://username:password@localhost:5432/notes_db
DB_HOST=localhost
DB_PORT=5432
DB_NAME=notes_db
DB_USER=username
DB_PASSWORD=password
# Application Configuration
DEBUG=True
SECRET_KEY=your-secret-key-here
APP_NAME=Notes GraphQL API
APP_VERSION=1.0.0
# GraphQL Configuration
GRAPHQL_DEBUG=True-
Start the server
python app/main.py
Or using uvicorn directly:
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
-
Access the application
- GraphQL Playground: http://localhost:8000/graphql
- Health Check: http://localhost:8000/health
- Root Info: http://localhost:8000/
query GetAllNotes {
getAllNotes {
success
message
notes {
id
title
content
isActive
createdAt
updatedAt
}
total
}
}query GetNote($id: Int!) {
getNote(id: $id) {
success
message
note {
id
title
content
isActive
createdAt
updatedAt
}
}
}query SearchNotes($searchInput: NoteSearchInput!) {
searchNotes(searchInput: $searchInput) {
success
message
notes {
id
title
content
isActive
createdAt
updatedAt
}
total
}
}query GetStatistics {
getNoteStatistics {
success
message
statistics {
totalNotes
activeNotes
serviceVersion
}
}
}mutation CreateNote($noteInput: NoteCreateInput!) {
createNote(noteInput: $noteInput) {
success
message
note {
id
title
content
isActive
createdAt
updatedAt
}
}
}mutation UpdateNote($noteInput: NoteUpdateInput!) {
updateNote(noteInput: $noteInput) {
success
message
note {
id
title
content
isActive
createdAt
updatedAt
}
}
}mutation DeleteNote($deleteInput: NoteDeleteInput!) {
deleteNote(deleteInput: $deleteInput) {
success
message
deletedId
}
}- Each class has one responsibility (models, repositories, services, etc.)
- Clear separation of concerns between layers
- Abstract base classes allow extension without modification
- Repository pattern enables different data access implementations
- All repository implementations can be substituted with their base class
- Service layer depends on abstractions, not concretions
- Focused interfaces for different operations (queries vs mutations)
- Separate input and output types for different use cases
- High-level modules don't depend on low-level modules
- Both depend on abstractions (interfaces)
- Follow PEP 8 guidelines
- Use type hints for all function signatures
- Comprehensive docstrings for all modules and functions
# Run tests (when implemented)
pytest
# Run with coverage
pytest --cov=app# Generate migration file
alembic revision --autogenerate -m "Description"
# Apply migrations
alembic upgrade headGET /- Root endpoint with basic informationGET /health- Health check endpointPOST /graphql- GraphQL endpointGET /graphql- GraphQL Playground (debug mode only)
The application implements comprehensive error handling:
- Validation errors with detailed messages
- Database connection error handling
- GraphQL error formatting
- Global exception handlers
Configurable logging with different levels:
- INFO: General application flow
- DEBUG: Detailed debugging information
- ERROR: Error conditions and exceptions
- Environment variables for sensitive data
- CORS configuration for cross-origin requests
- Input validation at multiple layers
- SQL injection prevention through SQLAlchemy
- Database connection pooling
- Efficient query patterns
- Pagination support for large datasets
- Async/await for non-blocking operations
This project is licensed under the MIT License.
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
For issues and questions, please open an issue on the GitHub repository.