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.1.0.tar.gz (17.7 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.1.0-py3-none-any.whl (18.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: django_approval_workflow-0.1.0.tar.gz
  • Upload date:
  • Size: 17.7 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.1.0.tar.gz
Algorithm Hash digest
SHA256 6dc1ee94daee431ea2387bfb4526f324d35bd7271b5ce7bb732222b75612333c
MD5 32745634f0235e2bbcf572c36b154987
BLAKE2b-256 e039a01d9eddec3721b3c77f438d60954e085b9d8e382f651d7efd4aadb4f646

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for django_approval_workflow-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3bfda17ff155762eeb66ba1dc72d81cf8290d75ba7c116f912d2e61a636a6bd1
MD5 15e4ef1be557403cd603b573ea3589d0
BLAKE2b-256 0314f2b339d4b9fe468071a3f36eaa5972ae77491669314682a4b40d2173e6a4

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