Можно ли установить логический столбец как уникальное ограничение в Flask-SQLalchemy? - PullRequest
0 голосов
/ 25 октября 2018

Можно ли настроить таблицу таким образом, чтобы в любой момент времени для одной записи можно было установить значение true?

У меня есть таблица «Пользователь» и таблица «Учетные данные».Пользователь может иметь один или несколько учетных данных, связанных с ним.Должен быть только один «Активный» учетные данные за один раз, который обозначен «активным» столбцом (Boolean) в таблице учетных данных.

Можно ли установить какое-то ограничение, чтобы предотвратить две записи«активный» одновременно?

Ответы [ 2 ]

0 голосов
/ 25 октября 2018

Вы можете использовать уникальное ограничение для предотвращения одновременной активности двух столбцов, но вам придется использовать True и None в качестве возможных значений, а не True и False.Это связано с тем, что уникальное ограничение будет разрешать только одно значение True в столбце, но также будет разрешать только одно значение False.Ни одно (или SQL NULL) значения не участвуют в ограничении уникальности, и поэтому вы можете иметь столько же тезисов, сколько и оставшихся строк.Чтобы обеспечить целостность базы данных, это, вероятно, лучше всего достигается с типом данных enum только с одним возможным значением.

import enum

class Active(enum.Enum):
    true = True

class Credentials(db.Model):
    active = db.Column(db.Enum(Active), unique=True)

Теперь вы можете использовать Active.true в качестве значения для указания активных учетных данных и None для всех остальныхучетные данные с обеспечением целостности на уровне базы данных.Если вы намеревались иметь одну активную учетную запись на пользователя, а не одну активную учетную запись в целом, этого можно достичь с помощью отдельного оператора UniqueConstraint.

class Credential(db.Model):
    __tablename__ = "credentials"
    __table_args__ = (db.UniqueConstraint('user_id', 'active'),)

    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
    user = db.relationship("User", back_populates="credentials")
    active = db.Column(db.Enum(Active))

class User(db.Model):
    __tablename__ = "users"

    id = db.Column(db.Integer, primary_key=True)
    credentials = db.relationship("Credential", back_populates="user")

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

0 голосов
/ 25 октября 2018

Так что, если я правильно читаю, у вас есть два класса моделей User и Credential, которые являются отношением один ко многим:

class User(db.Model):
    ...
    credentials = db.relationship('Credential')

class Credential(db.Model):
    ...
    user_id = db.Column(db.Integer, db.ForeignKey('user.id', nullable=False)

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

class User(db.Model):
    ...
    active_credential_id = db.Column(db.Integer, db.ForeignKey('credential.id'))

class Credential(db.Model):
    ...
    active_user = db.relationship('User')

Вы можете обновить это что-то вроде:

inactive_credential = # some credential from the user's list of credentials
user = User.query.filter(User.id == inactive_credential.user_id)
user.active_credential_id = inactive_credential.id
db.session.add(user)
db.session.commit()
# inactive_credential ==>> active_credential

Использование внешнего ключа здесь поддерживает целостность базы данных.

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

...