Django - Обработка "enum models"
Есть ли какая-либо передовая практика в обработке "таблиц поддержки" в 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),
)
... или что-то в этом роде.
Что вы используете?
Ответы
Ответ 1
Django ORM проверяет целостность, если вы указываете атрибут выбора (когда вы вставляете/обновляете данные через пользовательские формы).
Вы также можете установить логику проверки на уровень базы данных и использовать поле базы данных 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)
Ответ 2
У меня также есть вариант использования для поддерживаемых базой данных моделей Enum. Я предложил решение, использующее дескрипторы Python для реализации интерфейса выбора django -like со значениями перечисления:
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)>