Ограничить модель Джанго значением поля - PullRequest
2 голосов
/ 19 июня 2019

Рассмотрим следующую модель Django:

class Account(models.Model):

    ACCOUNT_CHOICES = [
        ('m', 'Main',),
        ('s','Secondary'),
        ('o', 'Other')
    ]
    user = models.ForeignKey(User)
    level = models.CharField(max_length=1, choices=ACCOUNT_CHOICES)

Как я могу применить ограничение базы данных максимум для одной учетной записи «Main» на пользователя, при этом позволяя пользователям любое количество «Secondary» или «Other»' Счета?В некотором смысле, я хочу unique_together для user и level, но только когда значение level равно m.

Я знаю, что могу вручную проверить сохранение, но япредпочел бы, чтобы база данных проверяла автоматически и в случае необходимости вызывала IntegrityError.

1 Ответ

2 голосов
/ 19 июня 2019

Я не думаю, что вы можете сделать это с вашей текущей моделью, но если это только два варианта для поля level, попробуйте заменить его на nullable BooleanField, например

is_main = models.BooleanField(null=True) 

и установите его на None для дополнительных учетных записей.Тогда unique_together будет работать, потому что каждое нулевое значение является уникальным для SQL (см. этот ответ ).

Поскольку существует больше вариантов для поля level, так как выуточнено позже, вы можете добавить третье поле и, возможно, переопределить метод .save(), чтобы он автоматически устанавливался на None, если level не "m" для дополнительного удобства.

Редактировать: Если вас не беспокоит переносимость, @ Trent предлагает, чтобы PostgreSQL поддерживал частичные уникальные индексы, например:

create unique index u_i on accounts(user_id, level_id) WHERE level_id = 'm';

Вот SQL Fiddle .

Редактировать 2: На самом деле похоже, что наконец-то можно создать частичные индексы в Django ORM, начиная с Django 2.2.Подробнее см. в этом вопросе .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...