djangoapprove


Namedjangoapprove JSON
Version 0.2.0 PyPI version JSON
download
home_pagehttps://github.com/ullauri/djangoapprove
SummaryA Django module to manage approval workflows for CRUD operations.
upload_time2024-11-11 01:02:49
maintainerNone
docs_urlNone
authorByron Cabrera
requires_python>=3.7
licenseMIT
keywords django approvals workflow crud
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # djangoapprove

djangoapprove is a Django module that manages approval workflows for CRUD operations on Django models. It allows interception of model operations (create, update, delete) and introduces a customizable approval flow before the changes are applied.

## Features
- **Approval Workflow**: Intercepts CRUD operations and creates approval requests.
- **Approval Types**: Supports creation, updates, and deletions.
- **Direct Operations**: Allows bypassing approval for direct operations.

## Installation

1. Install using `pip`:
   ```bash
   pip install djangoapprove
   ```
2. Add `djangoapprove` to your `INSTALLED_APPS` in `settings.py`:
```python
INSTALLED_APPS = [
    ...,
    'djangoapprove',
]
```
3. Run migrations to create the Approval model table:
```bash
python manage.py makemigrations djangoapprove
python manage.py migrate
```

## Usage

### Basic Integration
To integrate `djangoapprove` with a model, use the `ApprovalMixin` and the `ApprovalManager`:
```python
from django.db import models
from djangoapprove.mixins import ApprovalMixin, ApprovalManager

class MyModel(ApprovalMixin, models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField()

    objects = ApprovalManager() # or approval_objects = ApprovalManager for MyModel.approval_objects.create

    def get_unique_key(self):
        return f"mymodel-{self.pk or some_unique_property}"
```

---
### Approving Requests

Once an operation is intercepted, it creates an Approval record. Approvals can be reviewed and transitioned to the next state (e.g., APPROVED).

```python
from djangoapprove.models import Approval

# Approve a pending request
approval = Approval.objects.get(pk=1)
approval.transition("APPROVE")
```

---
### Settings

You can customize states, transitions, and initial/completed statuses in your `settings.py`:

```python
APPROVAL_ACTIONS = {
    "APPROVE": "Approve",
    "REJECT": "Reject",
}

APPROVAL_STATUSES = {
    "PENDING": "Pending",
    "APPROVED": "Approved",
    "REJECTED": "Rejected",
    "FAILED": "Failed",
}

APPROVAL_TRANSITIONS = {
    "APPROVE": {"PENDING": "APPROVED"}, # Applying APPROVE to PENDING results in APPROVED
    "REJECT": {"PENDING": "REJECTED"}, # Applying REJECT to PENDING results in REJECTED
}

APPROVAL_INITIAL_STATUS = "PENDING"
APPROVAL_COMPLETED_STATUS = "APPROVED"
```

---

### Example: Approval Workflow

1. Intercept Save Operation:
```python
instance = MyModel(name="Example", description="This is a test.")
approval = instance.save()  # Does not save immediately
```

2. Review The Approval:
```python
# Fetch the pending approval
approval = Approval.objects.filter(unique_key='Example').first()
print(approval.data)  # View the data payload
```

3. Approve The Request:
```python
approval.transition("APPROVE")
```

4. Verify Execution:
```python
# The instance should now be created
instance = MyModel.objects.get(name="Example")
```

### Direct Operations (Bypassing Approval)
If you need to bypass the approval process (e.g., for admin operations), you can use the direct_save and direct_delete methods:
```python
instance = MyModel(name="Direct Save Example", value=123)
instance.direct_save()
instance.direct_delete()
```

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/ullauri/djangoapprove",
    "name": "djangoapprove",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.7",
    "maintainer_email": null,
    "keywords": "django, approvals, workflow, CRUD",
    "author": "Byron Cabrera",
    "author_email": "byron.o.cabrera@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/3d/41/50b9b6311c21e4072d0d3464ec060061890e9e3d4c519f9b256161a06481/djangoapprove-0.2.0.tar.gz",
    "platform": null,
    "description": "# djangoapprove\n\ndjangoapprove is a Django module that manages approval workflows for CRUD operations on Django models. It allows interception of model operations (create, update, delete) and introduces a customizable approval flow before the changes are applied.\n\n## Features\n- **Approval Workflow**: Intercepts CRUD operations and creates approval requests.\n- **Approval Types**: Supports creation, updates, and deletions.\n- **Direct Operations**: Allows bypassing approval for direct operations.\n\n## Installation\n\n1. Install using `pip`:\n   ```bash\n   pip install djangoapprove\n   ```\n2. Add `djangoapprove` to your `INSTALLED_APPS` in `settings.py`:\n```python\nINSTALLED_APPS = [\n    ...,\n    'djangoapprove',\n]\n```\n3. Run migrations to create the Approval model table:\n```bash\npython manage.py makemigrations djangoapprove\npython manage.py migrate\n```\n\n## Usage\n\n### Basic Integration\nTo integrate `djangoapprove` with a model, use the `ApprovalMixin` and the `ApprovalManager`:\n```python\nfrom django.db import models\nfrom djangoapprove.mixins import ApprovalMixin, ApprovalManager\n\nclass MyModel(ApprovalMixin, models.Model):\n    name = models.CharField(max_length=100)\n    description = models.TextField()\n\n    objects = ApprovalManager() # or approval_objects = ApprovalManager for MyModel.approval_objects.create\n\n    def get_unique_key(self):\n        return f\"mymodel-{self.pk or some_unique_property}\"\n```\n\n---\n### Approving Requests\n\nOnce an operation is intercepted, it creates an Approval record. Approvals can be reviewed and transitioned to the next state (e.g., APPROVED).\n\n```python\nfrom djangoapprove.models import Approval\n\n# Approve a pending request\napproval = Approval.objects.get(pk=1)\napproval.transition(\"APPROVE\")\n```\n\n---\n### Settings\n\nYou can customize states, transitions, and initial/completed statuses in your `settings.py`:\n\n```python\nAPPROVAL_ACTIONS = {\n    \"APPROVE\": \"Approve\",\n    \"REJECT\": \"Reject\",\n}\n\nAPPROVAL_STATUSES = {\n    \"PENDING\": \"Pending\",\n    \"APPROVED\": \"Approved\",\n    \"REJECTED\": \"Rejected\",\n    \"FAILED\": \"Failed\",\n}\n\nAPPROVAL_TRANSITIONS = {\n    \"APPROVE\": {\"PENDING\": \"APPROVED\"}, # Applying APPROVE to PENDING results in APPROVED\n    \"REJECT\": {\"PENDING\": \"REJECTED\"}, # Applying REJECT to PENDING results in REJECTED\n}\n\nAPPROVAL_INITIAL_STATUS = \"PENDING\"\nAPPROVAL_COMPLETED_STATUS = \"APPROVED\"\n```\n\n---\n\n### Example: Approval Workflow\n\n1. Intercept Save Operation:\n```python\ninstance = MyModel(name=\"Example\", description=\"This is a test.\")\napproval = instance.save()  # Does not save immediately\n```\n\n2. Review The Approval:\n```python\n# Fetch the pending approval\napproval = Approval.objects.filter(unique_key='Example').first()\nprint(approval.data)  # View the data payload\n```\n\n3. Approve The Request:\n```python\napproval.transition(\"APPROVE\")\n```\n\n4. Verify Execution:\n```python\n# The instance should now be created\ninstance = MyModel.objects.get(name=\"Example\")\n```\n\n### Direct Operations (Bypassing Approval)\nIf you need to bypass the approval process (e.g., for admin operations), you can use the direct_save and direct_delete methods:\n```python\ninstance = MyModel(name=\"Direct Save Example\", value=123)\ninstance.direct_save()\ninstance.direct_delete()\n```\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A Django module to manage approval workflows for CRUD operations.",
    "version": "0.2.0",
    "project_urls": {
        "Homepage": "https://github.com/ullauri/djangoapprove",
        "Source": "https://github.com/ullauri/djangoapprove"
    },
    "split_keywords": [
        "django",
        " approvals",
        " workflow",
        " crud"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "353d525fad6dc00fadf02031047cf561b53a01ef7704b6e57dafdde827706e7e",
                "md5": "48309e2edce7ad29d46f3b7efeaea43d",
                "sha256": "2777e4433b17d9597b1e308474933ca1e274214292d9da77962cb583b718c559"
            },
            "downloads": -1,
            "filename": "djangoapprove-0.2.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "48309e2edce7ad29d46f3b7efeaea43d",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7",
            "size": 11356,
            "upload_time": "2024-11-11T01:02:47",
            "upload_time_iso_8601": "2024-11-11T01:02:47.636368Z",
            "url": "https://files.pythonhosted.org/packages/35/3d/525fad6dc00fadf02031047cf561b53a01ef7704b6e57dafdde827706e7e/djangoapprove-0.2.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "3d4150b9b6311c21e4072d0d3464ec060061890e9e3d4c519f9b256161a06481",
                "md5": "a73b3dda4143d395d3c0a5f7ba894778",
                "sha256": "f0edabeae8b327d80758709e35928eaea2a8af47d66c5e6ccc6c33c8e9cc1bf5"
            },
            "downloads": -1,
            "filename": "djangoapprove-0.2.0.tar.gz",
            "has_sig": false,
            "md5_digest": "a73b3dda4143d395d3c0a5f7ba894778",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7",
            "size": 10083,
            "upload_time": "2024-11-11T01:02:49",
            "upload_time_iso_8601": "2024-11-11T01:02:49.555408Z",
            "url": "https://files.pythonhosted.org/packages/3d/41/50b9b6311c21e4072d0d3464ec060061890e9e3d4c519f9b256161a06481/djangoapprove-0.2.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-11-11 01:02:49",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "ullauri",
    "github_project": "djangoapprove",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "requirements": [],
    "lcname": "djangoapprove"
}
        
Elapsed time: 0.33568s