Django - обработка "enum models" - PullRequest
       3

Django - обработка "enum models"

12 голосов
/ 09 марта 2012

Есть ли лучшая практика в работе с "таблицами поддержки" в Django?

Мне не нравится Field.choices, поскольку на самом деле это не обеспечивает целостность (даже не создает проверочных ограничений), поэтомупредпочитаю создавать полноценную модель (и часто я добавляю дополнительные поля в таблицу поддержки).

Теперь, если я использую полную модель, я полагаю, что правильный путь - это создать начальнуюданные для содержимого таблицы, но есть ли «правильный способ» именовать экземпляры строки, скажем ...

class State(models.Model):
    name = model.TextField()

STATES = dict(
    NEW=State.objects.get(pk=0),
    IN_PROGRESS=State.objects.get(pk=1),
)

... или что-то в этом роде.

Что вы используете?

Ответы [ 2 ]

8 голосов
/ 09 марта 2012

Django ORM проверяет целостность, если вы указываете атрибут choices (когда вы вставляете / обновляете данные через пользовательские формы).

Вы также можете установить логику проверки на уровень базы данных и использовать поле ENUM базы данных, если вы поддерживаете эту базу данных.

UPD :

class EnumField(models.Field):

    def __init__(self, *args, **kwargs):
        super(EnumField, self).__init__(*args, **kwargs)
        if not self.choices:
            raise AttributeError('EnumField requires `choices` attribute.')

    def db_type(self):
        return "enum(%s)" % ','.join("'%s'" % k for (k, _) in self.choices)

GENDER_MALE = 'm'
GENDER_FEMALE = 'f'
GENDER_CHOICES = (
    (GENDER_MALE, 'Male'),
    (GENDER_FEMALE, 'Female'),
)


class Person(models.Model):
    name = models.CharField(max_length=50)
    gender = EnumField(choices=GENDER_CHOICES)
1 голос
/ 29 июня 2019

У меня также есть сценарий использования для моделей Enum на основе базы данных. Я предложил решение, использующее дескрипторы Python для реализации django choices -подобного интерфейса со значениями перечисления:

from django.db import models

class ModelInstance:
    """Descriptor that uses predefined value fields to access model instances."""
    def __init__(self, **kwargs):
        self._instance_attributes = kwargs
        self._instance = None
    def __get__(self, instance, instance_type):
        if not self._instance:
            self._instance = instance_type.objects.get(**self._instance_attributes)
        return self._instance

class EnumModel(models.Model):
    name = models.CharField(max_length=100)
    JOHN = ModelInstance(name='John')
    FRED = ModelInstance(name='Fred')

JOHN и FRED - это лениво оцененные экземпляры модели, полученные для определенных параметров запроса (name=value). Я предполагаю, что запросы оцениваются по уникальным строкам в таблице.

Чтобы использовать его, сначала нужно добавить строки в базу данных для Джона и Фреда:

In [1]: EnumModel.objects.create(name="Fred")
In [2]: EnumModel.objects.create(name="John")

Затем вы можете получить доступ к экземплярам модели, используя атрибуты класса:

In [3]: EnumModel.JOHN                                                                                                                  
Out[3]: <EnumModel: EnumModel object (1)>
In [4]: EnumModel.FRED                                                                                                                  
Out[4]: <EnumModel: EnumModel object (2)>
...