Почему с помощью следующих моделей удается добавить дубликаты связей в отношения во время одной и той же транзакции?Я ожидал (и нуждаюсь), что он потерпит неудачу с UniqueConstraint, помещенным в таблицу ассоциации.
Модели:
from app import db # this is the access to SQLAlchemy
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
sz_shirt_dress_sleeve = db.relationship(
'SizeKeyShirtDressSleeve',
secondary=LinkUserSizeShirtDressSleeve,
backref=db.backref('users', lazy='dynamic'),
order_by="asc(SizeKeyShirtDressSleeve.id)")
class SizeKeyShirtDressSleeve(db.Model):
id = db.Column(db.Integer, primary_key=True)
size = db.Column(db.Integer)
def __repr__(self):
return 'Dress shirt sleeve size: %r' % self.size
LinkUserSizeShirtDressSleeve = db.Table(
'link_user_size_shirt_dress_sleeve',
db.Column(
'size_id',
db.Integer,
db.ForeignKey('size_key_shirt_dress_sleeve.id'), primary_key=True),
db.Column(
'user_id',
db.Integer,
db.ForeignKey('user.id'), primary_key=True),
db.UniqueConstraint('size_id', 'user_id', name='uq_association')
)
Из-за UniqueConstraint в таблице ассоциации я ожидал, что этот интерактивный сеанс будетвызвать ошибку IntegrityError.Это не позволяет и позволяет мне связать один и тот же размер дважды:
>>> from app.models import User, SizeKeyShirtDressSleeve
>>> db.session.add(User(id=8))
>>> db.session.commit()
>>> u = User.query.filter(User.id==8).one()
>>> u
<User id: 8, email: None, password_hash: None>
>>> u.sz_shirt_dress_sleeve
[]
>>> should_cause_error = SizeKeyShirtDressSleeve.query.first()
>>> should_cause_error
Dress shirt sleeve size: 3000
>>> u.sz_shirt_dress_sleeve.append(should_cause_error)
>>> u.sz_shirt_dress_sleeve.append(should_cause_error)
>>> u.sz_shirt_dress_sleeve
[Dress shirt sleeve size: 3000, Dress shirt sleeve size: 3000]
>>> db.session.commit()
>>>
Подождите, что?Разве эти отношения не отражают то, что находится в моей таблице ассоциации?Думаю, мне следует проверить, что:
(сразу после того же сеанса)
>>> from app.models import LinkUserSizeShirtDressSleeve as Sleeve
>>> db.session.query(Sleeve).filter(Sleeve.c.user_id==8).all()
[(1, 8)]
>>>
Так что u.sz_shirt_dress_sleeve
не точно представлял состояние таблицы ассоциации,...Хорошо.Но мне это нужно.На самом деле, я знаю, что это потерпит неудачу, если я попытаюсь добавить еще один should_cause_error
объект в отношения:
>>> u.sz_shirt_dress_sleeve.append(should_cause_error)
>>> db.session.commit()
# huge stack trace
sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: link_user_size_shirt_dress_sleeve.size_id, link_user_size_shirt_dress_sleeve.user_id [SQL: 'INSERT INTO link_user_size_shirt_dress_sleeve (size_id, user_id) VALUES (?, ?)'] [parameters: (1, 8)] (Background on this error at: http://sqlalche.me/e/gkpj)
>>>
Отлично!Итак, вот что я нахожу: 1) Возможно иметь дублирующиеся элементы в списке отношений.2) Возможно, что список отношений не точно отражает состояние таблицы ассоциации, за которую он отвечает.3) UniqueConstraint
работает ... до тех пор, пока я продолжаю взаимодействовать с отношениями в отдельных транзакциях (акцентировано на session.commit ()).
Вопросы: 1), 2) или 3)неправильно?И как я могу предотвратить дублирование элементов в моем списке отношений внутри одной и той же транзакции?