项目作者: 5monkeys

项目描述 :
Custom Django field for using enumerations of named constants
高级语言: Python
项目地址: git://github.com/5monkeys/django-enumfield.git
创建时间: 2013-01-31T10:34:44Z
项目社区:https://github.com/5monkeys/django-enumfield

开源协议:MIT License

下载


django-enumfield

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

Build Status
PyPi Version
License
Python Versions
Wheel
Coveralls github

Installation

Currently, we test Django versions 2.2-4.1 and Python versions 3.7-3.11.

Install django-enumfield in your Python environment:

  1. $ pip install django-enumfield

Upgrading from django-enumfield 1.x? See the migration guide

For use with Django versions prior to 1.8 use version
1.2.1

For use with Django versions prior to 1.11 use version
1.5

Usage

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

  1. from django.db import models
  2. from django_enumfield import enum
  3. class BeerStyle(enum.Enum):
  4. LAGER = 0
  5. STOUT = 1
  6. WEISSBIER = 2
  7. class Beer(models.Model):
  8. style = enum.EnumField(BeerStyle, default=BeerStyle.LAGER)
  9. # Use .get to get enum values from either name or ints
  10. print(BeerStyle.get("LAGER")) # <BeerStyle.LAGER: 0>
  11. print(BeerStyle.get(1)) # <BeerStyle.STOUT: 1>
  12. print(BeerStyle.get(BeerStyle.WEISSBIER)) # <BeerStyle.WEISSBIER: 2>
  13. # It's also possible to use the normal enum way to get the value
  14. print(BeerStyle(1)) # <BeerStyle.STOUT: 1>
  15. print(BeerStyle["LAGER"]) # <BeerStyle.LAGER: 0>
  16. # The enum value has easy access to their value and name
  17. print(BeerStyle.LAGER.value) # 0
  18. print(BeerStyle.LAGER.name) # "LAGER"

For more information about Python 3 enums
(which our Enum inherits, IntEnum to be specific)
checkout the docs.

Setting the default value

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

  1. from django.db import models
  2. from django_enumfield import enum
  3. class BeerStyle(enum.Enum):
  4. LAGER = 0
  5. STOUT = 1
  6. WEISSBIER = 2
  7. __default__ = LAGER
  8. class BeerStyleNoDefault(enum.Enum):
  9. LAGER = 0
  10. class Beer(models.Model):
  11. style_default_lager = enum.EnumField(BeerStyle)
  12. style_default_stout = enum.EnumField(BeerStyle, default=BeerStyle.STOUT)
  13. style_default_null = enum.EnumField(BeerStyleNoDefault, null=True, blank=True)
  14. # When you set __default__ attribute, you can access default value via
  15. # `.default()` method of your enum class
  16. assert BeerStyle.default() == BeerStyle.LAGER
  17. beer = Beer.objects.create()
  18. assert beer.style_default_larger == BeerStyle.LAGER
  19. assert beer.style_default_stout == BeerStyle.STOUT
  20. assert beer.style_default_null is None

Labels

You can use your own labels for Enum items

  1. from django.utils.translation import gettext_lazy
  2. from django_enumfield import enum
  3. class Animals(enum.Enum):
  4. CAT = 1
  5. DOG = 2
  6. SHARK = 3
  7. __labels__ = {
  8. CAT: gettext_lazy("Cat"),
  9. DOG: gettext_lazy("Dog"),
  10. }
  11. print(Animals.CAT.label) # "Cat"
  12. print(Animals.SHARK.label) # "SHARK"
  13. # There's also classmethods for getting the label
  14. print(Animals.get_label(2)) # "Dog"
  15. print(Animals.get_label("DOG")) # "Dog"

Validate transitions

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

  1. from django.db import models
  2. from django_enumfield import enum
  3. from django_enumfield.exceptions import InvalidStatusOperationError
  4. class PersonStatus(enum.Enum):
  5. ALIVE = 1
  6. DEAD = 2
  7. REANIMATED = 3
  8. __transitions__ = {
  9. DEAD: (ALIVE,), # Can go from ALIVE to DEAD
  10. REANIMATED: (DEAD,) # Can go from DEAD to REANIMATED
  11. }
  12. class Person(models.Model):
  13. status = enum.EnumField(PersonStatus)
  14. # These transitions state that a PersonStatus can only go to DEAD from ALIVE and to REANIMATED from DEAD.
  15. person = Person.objects.create(status=PersonStatus.ALIVE)
  16. try:
  17. person.status = PersonStatus.REANIMATED
  18. except InvalidStatusOperationError:
  19. print("Person status can not go from ALIVE to REANIMATED")
  20. else:
  21. # All good
  22. person.save()

In forms

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

  1. from django import forms
  2. from django_enumfield import enum
  3. from django_enumfield.forms.fields import EnumChoiceField
  4. class GenderEnum(enum.Enum):
  5. MALE = 1
  6. FEMALE = 2
  7. __labels__ = {
  8. MALE: "Male",
  9. FEMALE: "Female",
  10. }
  11. class PersonForm(forms.Form):
  12. 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.