Skip to main content

A powerful Django library for automatic GraphQL API generation with advanced features

Project description

Rail Django GraphQL

CI PyPI version Python versions Django versions License

A powerful Django library for automatic GraphQL schema generation with advanced features including type generation, query optimization, permissions, and comprehensive debugging tools.

Features

  • 🚀 Automatic Schema Generation: Generate GraphQL schemas from Django models with zero configuration
  • 🔧 Type Generators: Automatic GraphQL type creation with customizable field mappings
  • 🔍 Query Optimization: Built-in query optimization and N+1 problem prevention
  • 🛡️ Advanced Permissions: Flexible permission system with field-level access control
  • 🐛 Debugging Tools: Comprehensive debugging and introspection capabilities
  • 📊 Performance Monitoring: Built-in performance metrics and query analysis
  • 🔌 Plugin System: Extensible architecture with custom plugins
  • 🎨 GraphiQL Integration: Enhanced GraphiQL interface with custom tools
  • 📝 Auto Documentation: Automatic API documentation generation
  • 🔒 Security Features: Built-in security measures and validation

Installation

From PyPI (Recommended)

pip install rail-django-graphql

From GitHub (Development Version)

# Install directly from GitHub
pip install git+https://github.com/raillogistic/rail-django-graphql.git

# Or clone and install locally
git clone https://github.com/raillogistic/rail-django-graphql.git
cd rail-django-graphql
pip install -e .

Optional Dependencies

Install additional features:

# Authentication support
pip install rail-django-graphql[auth]

# Performance optimizations
pip install rail-django-graphql[performance]

# Media handling
pip install rail-django-graphql[media]

# Monitoring and metrics
pip install rail-django-graphql[monitoring]

# All optional features
pip install rail-django-graphql[all]

Quick Start

1. Add to Django Settings

# settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    
    # GraphQL dependencies
    'graphene_django',
    'django_filters',
    'corsheaders',
    
    # Rail Django GraphQL
    'rail_django_graphql',
    
    # Your apps
    'your_app',
]

# GraphQL Configuration
GRAPHENE = {
    'SCHEMA': 'your_project.schema.schema',
    'MIDDLEWARE': [
        'rail_django_graphql.middleware.QueryOptimizationMiddleware',
        'rail_django_graphql.middleware.PermissionMiddleware',
        'rail_django_graphql.middleware.DebuggingMiddleware',
    ],
}

# Rail Django GraphQL Settings
RAIL_GRAPHQL = {
    'AUTO_GENERATE_SCHEMA': True,
    'ENABLE_DEBUGGING': True,
    'ENABLE_INTROSPECTION': True,
    'MAX_QUERY_DEPTH': 10,
    'ENABLE_QUERY_OPTIMIZATION': True,
}

2. Create Your Schema

# schema.py
import graphene
from rail_django_graphql import (
    TypeGenerator,
    QueryGenerator,
    MutationGenerator,
    SchemaBuilder
)
from your_app.models import User, Post, Comment

# Generate types automatically
UserType = TypeGenerator.from_model(User)
PostType = TypeGenerator.from_model(Post)
CommentType = TypeGenerator.from_model(Comment)

# Generate queries
class Query(graphene.ObjectType):
    # Auto-generated queries
    users = QueryGenerator.list_field(User)
    user = QueryGenerator.detail_field(User)
    posts = QueryGenerator.list_field(Post)
    post = QueryGenerator.detail_field(Post)
    
    # Custom queries
    my_posts = graphene.List(PostType)
    
    def resolve_my_posts(self, info):
        return Post.objects.filter(author=info.context.user)

# Generate mutations
class Mutation(graphene.ObjectType):
    create_post = MutationGenerator.create_mutation(Post)
    update_post = MutationGenerator.update_mutation(Post)
    delete_post = MutationGenerator.delete_mutation(Post)

# Build schema
schema = SchemaBuilder.build(
    query=Query,
    mutation=Mutation,
    auto_discover=True  # Automatically discover and include all models
)

3. Add URLs

# urls.py
from django.contrib import admin
from django.urls import path, include
from graphene_django.views import GraphQLView
from rail_django_graphql.views.graphql_views import (
    MultiSchemaGraphQLView,
    SchemaListView,
    GraphQLPlaygroundView,
)
from rail_django_graphql.health_urls import health_urlpatterns

urlpatterns = [
    path('admin/', admin.site.urls),
    # Single schema endpoint (backward compatible)
    path('graphql/', GraphQLView.as_view(graphiql=True)),
    # Multi-schema endpoints
    path('graphql/<str:schema_name>/', MultiSchemaGraphQLView.as_view(), name='graphql-by-schema'),
    path('schemas/', SchemaListView.as_view(), name='graphql-schemas'),
    path('playground/<str:schema_name>/', GraphQLPlaygroundView.as_view(), name='graphql-playground'),
    # Health endpoints
    path('health/', include(health_urlpatterns)),
]

4. Run Migrations and Start Server

python manage.py migrate
python manage.py runserver

Visit http://localhost:8000/graphql/ to access the GraphiQL interface.

Advanced Usage

Multi-Schema Setup

The library supports multiple schemas with per-schema settings, endpoints, and GraphiQL control.

  1. Enable multi-schema in settings and register schemas via the registry:
# settings.py
RAIL_DJANGO_GRAPHQL = {
    "MULTI_SCHEMA_ENABLED": True,
}

# myapp/schema_config.py
from rail_django_graphql.core.registry import schema_registry

schema_registry.register_schema(
    name="public_api",
    description="Public API for customers",
    version="1.0.0",
    apps=["customers", "products"],
    models=["Customer", "Product"],
    enabled=True,
    settings={
        "enable_graphiql": True,
        "authentication_required": False,
    },
)

schema_registry.register_schema(
    name="admin_api",
    description="Admin API for internal use",
    version="1.0.0",
    apps=["customers", "products", "orders"],
    models=["Customer", "Product", "Order", "User"],
    enabled=True,
    settings={
        "enable_graphiql": True,
        "authentication_required": True,
    },
)
  1. Configure URLs to expose per-schema endpoints:
from django.urls import path
from rail_django_graphql.views.graphql_views import MultiSchemaGraphQLView, SchemaListView, GraphQLPlaygroundView

urlpatterns = [
    path('graphql/<str:schema_name>/', MultiSchemaGraphQLView.as_view(), name='graphql-by-schema'),
    path('schemas/', SchemaListView.as_view(), name='graphql-schemas'),
    path('playground/<str:schema_name>/', GraphQLPlaygroundView.as_view(), name='graphql-playground'),
]

Endpoints provided:

  • GET/POST /graphql/<schema_name>/ — Execute queries against the specified schema
  • GET /schemas/ — List registered schemas and their metadata
  • GET /playground/<schema_name>/ — Open a schema-specific GraphQL Playground
  1. Control per-schema authentication and GraphiQL:
schema_registry.register_schema(
    name="secure_api",
    enabled=True,
    settings={
        "authentication_required": True,
        "permission_classes": ["django.contrib.auth.permissions.IsAuthenticated"],
        "enable_graphiql": False,  # Disable GraphiQL for production
    },
)

See more details in rail_django_graphql/views/graphql_views.py and the integration tests in rail_django_graphql/tests/integration/test_multi_schema.py.

Custom Type Generation

from rail_django_graphql import TypeGenerator
from your_app.models import User

# Basic type generation
UserType = TypeGenerator.from_model(User)

# Advanced type generation with custom fields
UserType = TypeGenerator.from_model(
    User,
    fields=['id', 'username', 'email', 'first_name', 'last_name'],
    exclude_fields=['password'],
    custom_fields={
        'full_name': graphene.String(),
        'post_count': graphene.Int(),
    },
    custom_resolvers={
        'full_name': lambda user, info: f"{user.first_name} {user.last_name}",
        'post_count': lambda user, info: user.posts.count(),
    }
)

Permission System

from rail_django_graphql.permissions import BasePermission

class IsOwnerOrReadOnly(BasePermission):
    def has_permission(self, info, obj=None):
        if info.context.method == 'GET':
            return True
        return obj and obj.owner == info.context.user

# Apply to queries
posts = QueryGenerator.list_field(
    Post,
    permission_classes=[IsOwnerOrReadOnly]
)

Query Optimization

# Automatic optimization is enabled by default
# Manual optimization for complex queries
from rail_django_graphql.optimization import QueryOptimizer

class Query(graphene.ObjectType):
    posts = graphene.List(PostType)
    
    @QueryOptimizer.optimize(['author', 'comments__user'])
    def resolve_posts(self, info):
        return Post.objects.all()

Configuration

Settings Reference

RAIL_GRAPHQL = {
    # Schema Generation
    'AUTO_GENERATE_SCHEMA': True,
    'AUTO_DISCOVER_MODELS': True,
    'SCHEMA_OUTPUT_PATH': 'schema.json',
    
    # Security
    'ENABLE_INTROSPECTION': True,  # Disable in production
    'MAX_QUERY_DEPTH': 10,
    'MAX_QUERY_COMPLEXITY': 1000,
    'ENABLE_QUERY_WHITELIST': False,
    
    # Performance
    'ENABLE_QUERY_OPTIMIZATION': True,
    'ENABLE_DATALOADER': True,
    'CACHE_TIMEOUT': 300,
    
    # Debugging
    'ENABLE_DEBUGGING': True,  # Disable in production
    'LOG_QUERIES': True,
    'LOG_SLOW_QUERIES': True,
    'SLOW_QUERY_THRESHOLD': 1.0,  # seconds
    
    # Permissions
    'DEFAULT_PERMISSION_CLASSES': [
        'rail_django_graphql.permissions.IsAuthenticated',
    ],
    'ENABLE_FIELD_PERMISSIONS': True,
    
    # Extensions
    'ENABLE_EXTENSIONS': True,
    'EXTENSION_CLASSES': [
        'rail_django_graphql.extensions.QueryComplexityExtension',
        'rail_django_graphql.extensions.PerformanceExtension',
    ],
}

Development

Setting up Development Environment

# Clone the repository
git clone https://github.com/raillogistic/rail-django-graphql.git
cd rail-django-graphql

# Create virtual environment
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Install development dependencies
pip install -r requirements-dev.txt

# Install the package in development mode
pip install -e .

# Run tests
python -m pytest

# Run linting
black rail_django_graphql
isort rail_django_graphql
flake8 rail_django_graphql
mypy rail_django_graphql

Running Tests

# Run all tests
python -m pytest

# Run with coverage
python -m pytest --cov=rail_django_graphql --cov-report=html

# Run specific test file
python -m pytest rail_django_graphql/tests/test_generators.py

# Run with verbose output
python -m pytest -v

Contributing

We welcome contributions! Please see our Contributing Guide for details.

Development Workflow

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Add tests for your changes
  5. Run the test suite (python -m pytest)
  6. Run linting (black . && isort . && flake8)
  7. Commit your changes (git commit -m 'Add amazing feature')
  8. Push to the branch (git push origin feature/amazing-feature)
  9. Open a Pull Request

Documentation

Requirements

  • Python 3.8+
  • Django 4.2+
  • graphene-django 3.0+

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support

Acknowledgments

  • Built on top of Graphene-Django
  • Inspired by Django REST Framework's design patterns
  • Thanks to all contributors and the Django/GraphQL community

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rail_django_graphql-1.1.7.tar.gz (478.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rail_django_graphql-1.1.7-py3-none-any.whl (460.6 kB view details)

Uploaded Python 3

File details

Details for the file rail_django_graphql-1.1.7.tar.gz.

File metadata

  • Download URL: rail_django_graphql-1.1.7.tar.gz
  • Upload date:
  • Size: 478.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.8.10

File hashes

Hashes for rail_django_graphql-1.1.7.tar.gz
Algorithm Hash digest
SHA256 240da71695b80a5e82757f0db425b5141be5160f6ed258c1d4ec9db6ea0053a7
MD5 90a407070a51e0281ca29b346695cef7
BLAKE2b-256 8279b78c13ff76ea765501e719b815f3c4bccd47e6a02de5ab88fd12b043b9b7

See more details on using hashes here.

File details

Details for the file rail_django_graphql-1.1.7-py3-none-any.whl.

File metadata

File hashes

Hashes for rail_django_graphql-1.1.7-py3-none-any.whl
Algorithm Hash digest
SHA256 6f6e931ab5a84481ce3c1768e0ab90182a2a74c8d5244607b2de4e75a644b1c7
MD5 bcf7c22213d8d3009c3435b9fe4da3a5
BLAKE2b-256 48600121a12aeb2708b7e12997092435d2c73bc8409667fc5d66c12e5ef36b02

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page