Ограничение выбора поля выбора в классе модели

Этот ответ SO показывает, как ограничить поле выбора в форме. Однако у меня есть поле выбора с вариантами, которые никогда не должны быть показаны пользователю. Следовательно, я хочу ограничить опции поля выбора в классе модели, чтобы придерживаться принципа DRY и не дать себе забыть добавить код в будущие формы.

Вот простой пример:

UNIT_TYPES = Choices(
    (1, 'APARTMENT', 'Apartment'),
    (2, 'TOWNHOUSE', 'Townhouse'),
    (3, 'SINGLE_FAMILY', 'Single-family home'),
    (4, 'OTHER', 'Other') # Never show in any views
)

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

Есть идеи, как этого добиться?

Я бы создал другой набор вариантов в вашем файле models.py для тех, которые скрыты, например

UNIT_TYPES = Choices(
    (1, 'APARTMENT', 'Apartment'),
    (2, 'TOWNHOUSE', 'Townhouse'),
    (3, 'SINGLE_FAMILY', 'Single-family home'),
)

HIDDEN_TYPES = Choices(
    (4, 'OTHER', 'Other') # Never show in any views
)

Вы должны иметь возможность установить выбор модели как UNIT_TYPES + HIDDEN_TYPES и затем получить доступ к HIDDEN_TYPES в файле формы. Ссылаясь на ответ, на который вы ссылались, вы можете настроить функцию __init__(), чтобы установить варианты выбора на основе UNIT_TYPES и полностью игнорировать HIDDEN_TYPES.

Если в вашем приложении есть другие места, где пользователь может увидеть эти варианты, то вам нужно позаботиться о том, чтобы исключить скрытые типы. Насколько я знаю, нет способа сделать это более динамичным - метод модели __init__() не имеет доступа к объекту request, который сообщил бы вам, какой пользователь задействован.

Использование пользовательского менеджера, который всегда будет исключать один из ваших вариантов :

APARTMENT = 1
TOWNHOUSE = 2
SINGLE_FAMILY = 3
OTHER = 4
UNIT_TYPES = (
    (APARTMENT, 'Apartment'),
    (TOWNHOUSE, 'Townhouse'),
    (SINGLE_FAMILY, 'Single-family home'),
    (OTHER, 'Other')
)


class CustomManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().exclude(unit_type=OTHER)


class Model(models.Model):
    unit_type = models.IntegerField(
        choices=UNIT_TYPES,
        validators=[MinValueValidator(APARTMENT), MaxValueValidator(OTHER)]
    )

    objects = CustomManager()
Вернуться на верх