# django_state_choice_field
[![Checks & Tests](https://github.com/themrinalsinha/django_state_choice_field/actions/workflows/checks_and_tests.yaml/badge.svg)](https://github.com/themrinalsinha/django_state_choice_field/actions/workflows/checks_and_tests.yaml)
It includes a `StateChoiceField` that comes with reusable `TextChoices` and validation for state changes. This feature enhances flexibility and data integrity.
## Requirements
- Python 3.6+
- Django 2.2+
## Installation
To set up `django_state_choice_field`, you can easily install it with pip.
```shell
$ pip install django_state_choice_field
```
## Example
Consider a scenario where we have a model called `Order` that includes the storage of the order's payment status. This payment status can fall into one of the following in `PaymentStatus`.
It also defines the state transitions that are allowed for each state. For example, a payment status of `IN_PROGRESS` can only be changed to `FAILED` or `COMPLETED`. This is done by defining the `__states__` attribute in the `PaymentStatus` class which extends `StateEnum`.
```python
from django_state_choice_field import StateChoiceField, StateEnum
class PaymentStatus(StateEnum):
NOT_STARTED = "not_started", "Not Started"
IN_PROGRESS = "in_progress", "In Progress"
COMPLETED = "completed", "Completed"
FAILED = "failed", "Failed"
CANCELLED = "cancelled", "Cancelled"
NOT_REQUIRED = "not_required", "Not Required"
__states__ = {
NOT_STARTED: (),
IN_PROGRESS: (NOT_STARTED, FAILED),
FAILED: (IN_PROGRESS,),
COMPLETED: (IN_PROGRESS, NOT_REQUIRED),
NOT_REQUIRED: (IN_PROGRESS,),
CANCELLED: (NOT_STARTED, NOT_REQUIRED, FAILED, COMPLETED),
}
```
Model `Order` can be defined as follows. The `payment_status` field is defined as a `StateChoiceField` with the `PaymentStatus` enum class.
```python
from django.db import models
class Orders(models.Model):
product_name = models.CharField(max_length=100)
payment_status = StateChoiceField(
PaymentStatus, default=PaymentStatus.NOT_STARTED, max_length=20
)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
```
**Usage**
```shell
>>> order = Order.objects.create(product_name="Product 1")
>>> order.payment_status
<PaymentStatus.NOT_STARTED: 'not_started'>
>>> order.payment_status = PaymentStatus.IN_PROGRESS
>>> order.save()
>>> order.payment_status
<PaymentStatus.IN_PROGRESS: 'in_progress'>
# Now, if we try to change the payment status to CANCELLED, it will raise a InvalidTransitionError error.
>>> order.payment_status = PaymentStatus.CANCELLED
django_state_choice_field.exceptions.InvalidTransitionError: [in_progress -> cancelled is not a valid transition for PaymentStatus']
```
Raw data
{
"_id": null,
"home_page": "https://github.com/themrinalsinha/django_state_choice_field",
"name": "django-state-choice-field",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.6, <4",
"maintainer_email": "",
"keywords": "django_state_choice_field",
"author": "Mrinal Sinha",
"author_email": "me@mrinal.xyz",
"download_url": "https://files.pythonhosted.org/packages/2b/a1/fc03dfa68de4ba90c4b0149da37f9f2c5ad585e4d2a0ed2ddb894f83697f/django_state_choice_field-0.0.1.tar.gz",
"platform": null,
"description": "# django_state_choice_field\n[![Checks & Tests](https://github.com/themrinalsinha/django_state_choice_field/actions/workflows/checks_and_tests.yaml/badge.svg)](https://github.com/themrinalsinha/django_state_choice_field/actions/workflows/checks_and_tests.yaml)\n\nIt includes a `StateChoiceField` that comes with reusable `TextChoices` and validation for state changes. This feature enhances flexibility and data integrity.\n\n## Requirements\n- Python 3.6+\n- Django 2.2+\n\n## Installation\nTo set up `django_state_choice_field`, you can easily install it with pip.\n```shell\n$ pip install django_state_choice_field\n```\n\n## Example\nConsider a scenario where we have a model called `Order` that includes the storage of the order's payment status. This payment status can fall into one of the following in `PaymentStatus`.\n\nIt also defines the state transitions that are allowed for each state. For example, a payment status of `IN_PROGRESS` can only be changed to `FAILED` or `COMPLETED`. This is done by defining the `__states__` attribute in the `PaymentStatus` class which extends `StateEnum`.\n```python\nfrom django_state_choice_field import StateChoiceField, StateEnum\n\nclass PaymentStatus(StateEnum):\n NOT_STARTED = \"not_started\", \"Not Started\"\n IN_PROGRESS = \"in_progress\", \"In Progress\"\n COMPLETED = \"completed\", \"Completed\"\n FAILED = \"failed\", \"Failed\"\n CANCELLED = \"cancelled\", \"Cancelled\"\n NOT_REQUIRED = \"not_required\", \"Not Required\"\n\n __states__ = {\n NOT_STARTED: (),\n IN_PROGRESS: (NOT_STARTED, FAILED),\n FAILED: (IN_PROGRESS,),\n COMPLETED: (IN_PROGRESS, NOT_REQUIRED),\n NOT_REQUIRED: (IN_PROGRESS,),\n CANCELLED: (NOT_STARTED, NOT_REQUIRED, FAILED, COMPLETED),\n }\n```\nModel `Order` can be defined as follows. The `payment_status` field is defined as a `StateChoiceField` with the `PaymentStatus` enum class.\n```python\nfrom django.db import models\n\nclass Orders(models.Model):\n product_name = models.CharField(max_length=100)\n payment_status = StateChoiceField(\n PaymentStatus, default=PaymentStatus.NOT_STARTED, max_length=20\n )\n created_at = models.DateTimeField(auto_now_add=True)\n updated_at = models.DateTimeField(auto_now=True)\n```\n\n**Usage**\n```shell\n>>> order = Order.objects.create(product_name=\"Product 1\")\n>>> order.payment_status\n<PaymentStatus.NOT_STARTED: 'not_started'>\n\n>>> order.payment_status = PaymentStatus.IN_PROGRESS\n>>> order.save()\n\n>>> order.payment_status\n<PaymentStatus.IN_PROGRESS: 'in_progress'>\n\n# Now, if we try to change the payment status to CANCELLED, it will raise a InvalidTransitionError error.\n>>> order.payment_status = PaymentStatus.CANCELLED\n\ndjango_state_choice_field.exceptions.InvalidTransitionError: [in_progress -> cancelled is not a valid transition for PaymentStatus']\n```\n",
"bugtrack_url": null,
"license": "",
"summary": "A Django enum field",
"version": "0.0.1",
"project_urls": {
"Homepage": "https://github.com/themrinalsinha/django_state_choice_field"
},
"split_keywords": [
"django_state_choice_field"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "9d958613da1219aab156e54a3ef5bd52d27989cca0c1d799a049b0d104b0ca8a",
"md5": "907c93ad1b0c083a386f1bab337bffcf",
"sha256": "daee1dae1636e20d603bf0a2de89fa08bd07ef88999a805f7dde9b840ba6b254"
},
"downloads": -1,
"filename": "django_state_choice_field-0.0.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "907c93ad1b0c083a386f1bab337bffcf",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.6, <4",
"size": 7932,
"upload_time": "2023-11-05T16:29:49",
"upload_time_iso_8601": "2023-11-05T16:29:49.549809Z",
"url": "https://files.pythonhosted.org/packages/9d/95/8613da1219aab156e54a3ef5bd52d27989cca0c1d799a049b0d104b0ca8a/django_state_choice_field-0.0.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "2ba1fc03dfa68de4ba90c4b0149da37f9f2c5ad585e4d2a0ed2ddb894f83697f",
"md5": "786c9035911b24d61907688c3978824f",
"sha256": "ff4e36c13a618403894fb0518509948c294d80da1938a3670ba7076952338328"
},
"downloads": -1,
"filename": "django_state_choice_field-0.0.1.tar.gz",
"has_sig": false,
"md5_digest": "786c9035911b24d61907688c3978824f",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.6, <4",
"size": 6901,
"upload_time": "2023-11-05T16:29:52",
"upload_time_iso_8601": "2023-11-05T16:29:52.429231Z",
"url": "https://files.pythonhosted.org/packages/2b/a1/fc03dfa68de4ba90c4b0149da37f9f2c5ad585e4d2a0ed2ddb894f83697f/django_state_choice_field-0.0.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-11-05 16:29:52",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "themrinalsinha",
"github_project": "django_state_choice_field",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "django-state-choice-field"
}