django-enumfield


Namedjango-enumfield JSON
Version 3.1 PyPI version JSON
download
home_pagehttp://github.com/5monkeys/django-enumfield
SummaryCustom Django field for using enumerations of named constants
upload_time2023-02-27 10:43:29
maintainer
docs_urlNone
authorHannes Ljungberg
requires_python
licenseMIT
keywords django enum field status state choices form model
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # django-enumfield

Provides an enumeration Django model field (using `IntegerField`) with reusable enums and transition validation.

[![Build Status](https://github.com/5monkeys/django-enumfield/workflows/Test/badge.svg)](https://github.com/5monkeys/django-enumfield/actions)
[![PyPi Version](https://img.shields.io/pypi/v/django-enumfield.svg)](https://pypi.python.org/pypi/django-enumfield)
[![License](https://img.shields.io/pypi/l/django-enumfield.svg)](https://pypi.python.org/pypi/django-enumfield)
[![Python Versions](https://img.shields.io/pypi/pyversions/django-enumfield.svg)](https://pypi.python.org/pypi/django-enumfield)
[![Wheel](https://img.shields.io/pypi/wheel/django-enumfield.svg)](https://pypi.python.org/pypi/django-enumfield)
![Coveralls github](https://img.shields.io/coveralls/github/5monkeys/django-enumfield)

Installation
------------

Currently, [we test](https://github.com/5monkeys/django-enumfield/actions) Django versions 2.2-4.1 and Python versions 3.7-3.11.

Install `django-enumfield` in your Python environment:

```sh
$ pip install django-enumfield
```

**Upgrading from django-enumfield 1.x?** [See the migration guide](docs/migrate-to-20.md)

For use with Django versions prior to 1.8 use version
[`1.2.1`](https://github.com/5monkeys/django-enumfield/tree/1.2.1)

For use with Django versions prior to 1.11 use version
[`1.5`](https://github.com/5monkeys/django-enumfield/tree/1.5)

Usage
-----

Create an `Enum`-class and pass it as first argument to the Django model `EnumField`.

```python
from django.db import models
from django_enumfield import enum


class BeerStyle(enum.Enum):
    LAGER = 0
    STOUT = 1
    WEISSBIER = 2


class Beer(models.Model):
    style = enum.EnumField(BeerStyle, default=BeerStyle.LAGER)


# Use .get to get enum values from either name or ints
print(BeerStyle.get("LAGER"))  # <BeerStyle.LAGER: 0>
print(BeerStyle.get(1))  # <BeerStyle.STOUT: 1>
print(BeerStyle.get(BeerStyle.WEISSBIER))  # <BeerStyle.WEISSBIER: 2>

# It's also possible to use the normal enum way to get the value
print(BeerStyle(1))  # <BeerStyle.STOUT: 1>
print(BeerStyle["LAGER"])  # <BeerStyle.LAGER: 0>

# The enum value has easy access to their value and name
print(BeerStyle.LAGER.value)  # 0
print(BeerStyle.LAGER.name)  # "LAGER"
```

For more information about Python 3 enums
(which our `Enum` inherits, `IntEnum` to be specific)
checkout the [docs](https://docs.python.org/3/library/enum.html).


### Setting the default value

You can also set default value on your enum class using `__default__`
attribute

```python
from django.db import models
from django_enumfield import enum


class BeerStyle(enum.Enum):
    LAGER = 0
    STOUT = 1
    WEISSBIER = 2

    __default__ = LAGER


class BeerStyleNoDefault(enum.Enum):
    LAGER = 0


class Beer(models.Model):
    style_default_lager = enum.EnumField(BeerStyle)
    style_default_stout = enum.EnumField(BeerStyle, default=BeerStyle.STOUT)
    style_default_null = enum.EnumField(BeerStyleNoDefault, null=True, blank=True)


# When you set __default__ attribute, you can access default value via
# `.default()` method of your enum class
assert BeerStyle.default() == BeerStyle.LAGER

beer = Beer.objects.create()
assert beer.style_default_larger == BeerStyle.LAGER
assert beer.style_default_stout == BeerStyle.STOUT
assert beer.style_default_null is None
```

### Labels

You can use your own labels for `Enum` items

```python
from django.utils.translation import gettext_lazy
from django_enumfield import enum


class Animals(enum.Enum):
    CAT = 1
    DOG = 2
    SHARK = 3

    __labels__ = {
        CAT: gettext_lazy("Cat"),
        DOG: gettext_lazy("Dog"),
    }


print(Animals.CAT.label)  # "Cat"
print(Animals.SHARK.label)  # "SHARK"

# There's also classmethods for getting the label
print(Animals.get_label(2))  # "Dog"
print(Animals.get_label("DOG"))  # "Dog"
```

### Validate transitions

The `Enum`-class provides the possibility to use transition validation.

```python
from django.db import models
from django_enumfield import enum
from django_enumfield.exceptions import InvalidStatusOperationError


class PersonStatus(enum.Enum):
    ALIVE = 1
    DEAD = 2
    REANIMATED = 3

    __transitions__ = {
        DEAD: (ALIVE,),  # Can go from ALIVE to DEAD
        REANIMATED: (DEAD,)  # Can go from DEAD to REANIMATED
    }


class Person(models.Model):
    status = enum.EnumField(PersonStatus)

# These transitions state that a PersonStatus can only go to DEAD from ALIVE and to REANIMATED from DEAD.
person = Person.objects.create(status=PersonStatus.ALIVE)
try:
    person.status = PersonStatus.REANIMATED
except InvalidStatusOperationError:
    print("Person status can not go from ALIVE to REANIMATED")
else:
    # All good
    person.save()
```

### In forms

The `Enum`-class can also be used without the `EnumField`. This is very useful in Django form `ChoiceField`s.

```python
from django import forms
from django_enumfield import enum
from django_enumfield.forms.fields import EnumChoiceField


class GenderEnum(enum.Enum):
    MALE = 1
    FEMALE = 2

    __labels__ = {
        MALE: "Male",
        FEMALE: "Female",
    }


class PersonForm(forms.Form):
    gender = EnumChoiceField(GenderEnum)
```

Rendering `PersonForm` in a template will generate a select-box with "Male" and "Female" as option labels for the gender field.


Local Development Environment
-----------------------------

Make sure black and isort is installed in your env with `pip install -e .[dev]`.

Before committing run `make format` to apply black and isort to all files.



            

Raw data

            {
    "_id": null,
    "home_page": "http://github.com/5monkeys/django-enumfield",
    "name": "django-enumfield",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "django,enum,field,status,state,choices,form,model",
    "author": "Hannes Ljungberg",
    "author_email": "hannes@5monkeys.se",
    "download_url": "https://files.pythonhosted.org/packages/11/1b/5ddfea406fbae8d32115f9f51241de76966b28f0ac91efb90badfac1ac97/django-enumfield-3.1.tar.gz",
    "platform": "any",
    "description": "# django-enumfield\n\nProvides an enumeration Django model field (using `IntegerField`) with reusable enums and transition validation.\n\n[![Build Status](https://github.com/5monkeys/django-enumfield/workflows/Test/badge.svg)](https://github.com/5monkeys/django-enumfield/actions)\n[![PyPi Version](https://img.shields.io/pypi/v/django-enumfield.svg)](https://pypi.python.org/pypi/django-enumfield)\n[![License](https://img.shields.io/pypi/l/django-enumfield.svg)](https://pypi.python.org/pypi/django-enumfield)\n[![Python Versions](https://img.shields.io/pypi/pyversions/django-enumfield.svg)](https://pypi.python.org/pypi/django-enumfield)\n[![Wheel](https://img.shields.io/pypi/wheel/django-enumfield.svg)](https://pypi.python.org/pypi/django-enumfield)\n![Coveralls github](https://img.shields.io/coveralls/github/5monkeys/django-enumfield)\n\nInstallation\n------------\n\nCurrently, [we test](https://github.com/5monkeys/django-enumfield/actions) Django versions 2.2-4.1 and Python versions 3.7-3.11.\n\nInstall `django-enumfield` in your Python environment:\n\n```sh\n$ pip install django-enumfield\n```\n\n**Upgrading from django-enumfield 1.x?** [See the migration guide](docs/migrate-to-20.md)\n\nFor use with Django versions prior to 1.8 use version\n[`1.2.1`](https://github.com/5monkeys/django-enumfield/tree/1.2.1)\n\nFor use with Django versions prior to 1.11 use version\n[`1.5`](https://github.com/5monkeys/django-enumfield/tree/1.5)\n\nUsage\n-----\n\nCreate an `Enum`-class and pass it as first argument to the Django model `EnumField`.\n\n```python\nfrom django.db import models\nfrom django_enumfield import enum\n\n\nclass BeerStyle(enum.Enum):\n    LAGER = 0\n    STOUT = 1\n    WEISSBIER = 2\n\n\nclass Beer(models.Model):\n    style = enum.EnumField(BeerStyle, default=BeerStyle.LAGER)\n\n\n# Use .get to get enum values from either name or ints\nprint(BeerStyle.get(\"LAGER\"))  # <BeerStyle.LAGER: 0>\nprint(BeerStyle.get(1))  # <BeerStyle.STOUT: 1>\nprint(BeerStyle.get(BeerStyle.WEISSBIER))  # <BeerStyle.WEISSBIER: 2>\n\n# It's also possible to use the normal enum way to get the value\nprint(BeerStyle(1))  # <BeerStyle.STOUT: 1>\nprint(BeerStyle[\"LAGER\"])  # <BeerStyle.LAGER: 0>\n\n# The enum value has easy access to their value and name\nprint(BeerStyle.LAGER.value)  # 0\nprint(BeerStyle.LAGER.name)  # \"LAGER\"\n```\n\nFor more information about Python 3 enums\n(which our `Enum` inherits, `IntEnum` to be specific)\ncheckout the [docs](https://docs.python.org/3/library/enum.html).\n\n\n### Setting the default value\n\nYou can also set default value on your enum class using `__default__`\nattribute\n\n```python\nfrom django.db import models\nfrom django_enumfield import enum\n\n\nclass BeerStyle(enum.Enum):\n    LAGER = 0\n    STOUT = 1\n    WEISSBIER = 2\n\n    __default__ = LAGER\n\n\nclass BeerStyleNoDefault(enum.Enum):\n    LAGER = 0\n\n\nclass Beer(models.Model):\n    style_default_lager = enum.EnumField(BeerStyle)\n    style_default_stout = enum.EnumField(BeerStyle, default=BeerStyle.STOUT)\n    style_default_null = enum.EnumField(BeerStyleNoDefault, null=True, blank=True)\n\n\n# When you set __default__ attribute, you can access default value via\n# `.default()` method of your enum class\nassert BeerStyle.default() == BeerStyle.LAGER\n\nbeer = Beer.objects.create()\nassert beer.style_default_larger == BeerStyle.LAGER\nassert beer.style_default_stout == BeerStyle.STOUT\nassert beer.style_default_null is None\n```\n\n### Labels\n\nYou can use your own labels for `Enum` items\n\n```python\nfrom django.utils.translation import gettext_lazy\nfrom django_enumfield import enum\n\n\nclass Animals(enum.Enum):\n    CAT = 1\n    DOG = 2\n    SHARK = 3\n\n    __labels__ = {\n        CAT: gettext_lazy(\"Cat\"),\n        DOG: gettext_lazy(\"Dog\"),\n    }\n\n\nprint(Animals.CAT.label)  # \"Cat\"\nprint(Animals.SHARK.label)  # \"SHARK\"\n\n# There's also classmethods for getting the label\nprint(Animals.get_label(2))  # \"Dog\"\nprint(Animals.get_label(\"DOG\"))  # \"Dog\"\n```\n\n### Validate transitions\n\nThe `Enum`-class provides the possibility to use transition validation.\n\n```python\nfrom django.db import models\nfrom django_enumfield import enum\nfrom django_enumfield.exceptions import InvalidStatusOperationError\n\n\nclass PersonStatus(enum.Enum):\n    ALIVE = 1\n    DEAD = 2\n    REANIMATED = 3\n\n    __transitions__ = {\n        DEAD: (ALIVE,),  # Can go from ALIVE to DEAD\n        REANIMATED: (DEAD,)  # Can go from DEAD to REANIMATED\n    }\n\n\nclass Person(models.Model):\n    status = enum.EnumField(PersonStatus)\n\n# These transitions state that a PersonStatus can only go to DEAD from ALIVE and to REANIMATED from DEAD.\nperson = Person.objects.create(status=PersonStatus.ALIVE)\ntry:\n    person.status = PersonStatus.REANIMATED\nexcept InvalidStatusOperationError:\n    print(\"Person status can not go from ALIVE to REANIMATED\")\nelse:\n    # All good\n    person.save()\n```\n\n### In forms\n\nThe `Enum`-class can also be used without the `EnumField`. This is very useful in Django form `ChoiceField`s.\n\n```python\nfrom django import forms\nfrom django_enumfield import enum\nfrom django_enumfield.forms.fields import EnumChoiceField\n\n\nclass GenderEnum(enum.Enum):\n    MALE = 1\n    FEMALE = 2\n\n    __labels__ = {\n        MALE: \"Male\",\n        FEMALE: \"Female\",\n    }\n\n\nclass PersonForm(forms.Form):\n    gender = EnumChoiceField(GenderEnum)\n```\n\nRendering `PersonForm` in a template will generate a select-box with \"Male\" and \"Female\" as option labels for the gender field.\n\n\nLocal Development Environment\n-----------------------------\n\nMake sure black and isort is installed in your env with `pip install -e .[dev]`.\n\nBefore committing run `make format` to apply black and isort to all files.\n\n\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Custom Django field for using enumerations of named constants",
    "version": "3.1",
    "project_urls": {
        "Download": "https://github.com/5monkeys/django-enumfield/tarball/3.1",
        "Homepage": "http://github.com/5monkeys/django-enumfield"
    },
    "split_keywords": [
        "django",
        "enum",
        "field",
        "status",
        "state",
        "choices",
        "form",
        "model"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "1b1b8eb7a8f32db6c1ced36d3f9b6cfb829459adfe0145f91262414594588063",
                "md5": "c9647b11d6c23cac451daf4cdb2227f6",
                "sha256": "e6a9e14f3a7cfbf15a14f3809117eacd9c0c4257e1730030f22ae07cd1793bbd"
            },
            "downloads": -1,
            "filename": "django_enumfield-3.1-py2.py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "c9647b11d6c23cac451daf4cdb2227f6",
            "packagetype": "bdist_wheel",
            "python_version": "py2.py3",
            "requires_python": null,
            "size": 18043,
            "upload_time": "2023-02-27T10:43:27",
            "upload_time_iso_8601": "2023-02-27T10:43:27.143055Z",
            "url": "https://files.pythonhosted.org/packages/1b/1b/8eb7a8f32db6c1ced36d3f9b6cfb829459adfe0145f91262414594588063/django_enumfield-3.1-py2.py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "111b5ddfea406fbae8d32115f9f51241de76966b28f0ac91efb90badfac1ac97",
                "md5": "6d1db76732f4fedffd98f0bfab4a11f3",
                "sha256": "abbb361507ad481bb2ef50a86ee4dc9ec770adbbabbe53c1242815defbf81889"
            },
            "downloads": -1,
            "filename": "django-enumfield-3.1.tar.gz",
            "has_sig": false,
            "md5_digest": "6d1db76732f4fedffd98f0bfab4a11f3",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 19491,
            "upload_time": "2023-02-27T10:43:29",
            "upload_time_iso_8601": "2023-02-27T10:43:29.251507Z",
            "url": "https://files.pythonhosted.org/packages/11/1b/5ddfea406fbae8d32115f9f51241de76966b28f0ac91efb90badfac1ac97/django-enumfield-3.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-02-27 10:43:29",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "5monkeys",
    "github_project": "django-enumfield",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "tox": true,
    "lcname": "django-enumfield"
}
        
Elapsed time: 0.37463s