Skip to main content

A powerful, flexible Django package for implementing dynamic multi-step approval workflows

Project description

Django Approval Workflow

Python Version Django Version License

A powerful, flexible, and reusable Django package for implementing dynamic multi-step approval workflows in your Django applications.

✨ Features

  • Dynamic Workflow Creation: Create approval workflows for any Django model using GenericForeignKey
  • Multi-Step Approval Process: Support for sequential approval steps with role-based assignments
  • Role-Based Permissions: Hierarchical role support using MPTT (Modified Preorder Tree Traversal)
  • Flexible Actions: Approve, reject, or request resubmission at any step
  • REST API Ready: Built-in REST API endpoints using Django REST Framework
  • Django Admin Integration: Full admin interface for managing workflows
  • Extensible Handlers: Custom hook system for workflow events
  • Form Integration: Optional dynamic form support for approval steps
  • Comprehensive Testing: Full test suite with pytest

🚀 Quick Start

Installation

pip install django-approval-workflow

Django Settings

Add approval_workflow to your INSTALLED_APPS:

INSTALLED_APPS = [
    # ... your apps
    'approval_workflow',
    'mptt',  # Required for hierarchical roles
    'rest_framework',  # Optional, for API endpoints
]

Optional Settings

# Custom role model (must inherit from MPTTModel)
APPROVAL_ROLE_MODEL = "myapp.Role"  # Default: None

# Field name linking User to Role model
APPROVAL_ROLE_FIELD = "role"  # Default: "role"

# Custom form model for dynamic forms
APPROVAL_DYNAMIC_FORM_MODEL = "myapp.DynamicForm"  # Default: None

Run Migrations

python manage.py migrate approval_workflow

📖 Usage

Basic Example

from approval_workflow.services import start_flow, advance_flow
from approval_workflow.utils import can_user_approve
from django.contrib.auth import get_user_model

User = get_user_model()

# Create users
manager = User.objects.get(username='manager')
employee = User.objects.get(username='employee')

# Your model instance
document = MyDocument.objects.create(title="Important Document")

# Start an approval workflow
flow = start_flow(
    obj=document,
    steps=[
        {"step": 1, "assigned_to": employee},
        {"step": 2, "assigned_to": manager},
    ]
)

# Check if user can approve
first_step = flow.instances.get(step_number=1)
if can_user_approve(first_step, employee):
    # Advance the workflow
    next_step = advance_flow(
        instance=first_step,
        action="approved",
        user=employee,
        comment="Looks good to me!"
    )

Role-Based Approval

With hierarchical roles (using MPTT):

# models.py
from mptt.models import MPTTModel, TreeForeignKey
from django.contrib.auth.models import AbstractUser

class Role(MPTTModel):
    name = models.CharField(max_length=100)
    parent = TreeForeignKey('self', on_delete=models.CASCADE, 
                           null=True, blank=True, related_name='children')

class User(AbstractUser):
    role = models.ForeignKey(Role, on_delete=models.SET_NULL, null=True)

# Usage
senior_role = Role.objects.create(name="Senior Manager")
junior_role = Role.objects.create(name="Junior Manager", parent=senior_role)

senior_user = User.objects.create(username="senior", role=senior_role)
junior_user = User.objects.create(username="junior", role=junior_role)

# Senior users can approve tasks assigned to junior users
instance = ApprovalInstance.objects.create(assigned_to=junior_user)
assert can_user_approve(instance, senior_user)  # True

Custom Handlers

Create custom handlers for workflow events:

# myapp/approval.py
from approval_workflow.handlers import BaseApprovalHandler

class MyDocumentApprovalHandler(BaseApprovalHandler):
    def on_approve(self, instance):
        # Custom logic when a step is approved
        print(f"Step {instance.step_number} approved!")
    
    def on_final_approve(self, instance):
        # Custom logic when workflow is complete
        instance.flow.target.status = 'approved'
        instance.flow.target.save()
    
    def on_reject(self, instance):
        # Custom logic when a step is rejected
        instance.flow.target.status = 'rejected'
        instance.flow.target.save()

🏗️ Models

ApprovalFlow

Central model that links to any Django model via GenericForeignKey.

ApprovalInstance

Represents individual steps in the approval process with status tracking.

🔧 Configuration

Role Model Requirements

If using role-based approvals, your role model must:

  • Inherit from MPTTModel
  • Implement hierarchical relationships
  • Be linked to your User model

Custom Form Integration

For dynamic forms in approval steps:

  • Configure APPROVAL_DYNAMIC_FORM_MODEL
  • Form model should have a schema field for validation

🧪 Testing

Run the test suite:

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

# Run tests
pytest

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📄 License

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

👨‍💻 Author

Mohamed Salah
Email: info@codxi.com
GitHub: Codxi-Co

🙏 Acknowledgments

  • Django team for the amazing framework
  • MPTT library for hierarchical model support
  • Django REST Framework for API capabilities

For more detailed documentation and examples, visit our documentation.

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

django_approval_workflow-0.2.0.tar.gz (17.9 kB view details)

Uploaded Source

Built Distribution

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

django_approval_workflow-0.2.0-py3-none-any.whl (18.2 kB view details)

Uploaded Python 3

File details

Details for the file django_approval_workflow-0.2.0.tar.gz.

File metadata

  • Download URL: django_approval_workflow-0.2.0.tar.gz
  • Upload date:
  • Size: 17.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.9

File hashes

Hashes for django_approval_workflow-0.2.0.tar.gz
Algorithm Hash digest
SHA256 fa4fcda92011292cbace3be864b4775ef78c03fd19b345966fcaed4c78c7db6a
MD5 4ba7b2d9237c52392291417e1b329836
BLAKE2b-256 781c5d06c1d797f13dbea0eb759be85271b8bae6d50343fa3ba58a065c53986d

See more details on using hashes here.

File details

Details for the file django_approval_workflow-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for django_approval_workflow-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ea06fb07bb12e4b3b6a82f41725cb756aa8951f5da304a66636b0f8d76534860
MD5 4a5ed384586bb04e8e3eac750ffebc60
BLAKE2b-256 4a5dc038b126760def9a14a095bae6706b0355ae8cd2ab79e670e7265d12568b

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