Flask中的一对一关系

4 投票
2 回答
17517 浏览
提问于 2025-04-18 14:36

我正在尝试在Flask中使用SqlAlchemy创建一对一的关系。我参考了之前的一篇帖子,并创建了如下的类:

class Image(db.Model):
    __tablename__ = 'image'
    image_id = db.Column(db.Integer, primary_key = True)
    name = db.Column(db.String(8))

class Blindmap(db.Model):
    __tablename__ = 'blindmap'
    module_id = db.Column(db.Integer, primary_key = True)
    image_id = db.Column(db.Integer, ForeignKey('image.image_id'))

虽然我可以将模型迁移到sqlite3数据库,但当我尝试创建一个对象并提供另一个类的值作为image_id时,却出现了错误。例如:

image1 = Image(image_id=1, name='image1.png')
blindmap1 = Blindmap(module_id=1, image_id=1)

我遇到的错误如下。我不太明白这个完整性错误到底是什么。我也尝试在创建blindmap1时直接插入对象,但没有成功。

======================================================================
ERROR: test_commit_blindmap (__main__.TestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "tests.py", line 183, in test_commit_blindmap
  blindmap1.add_label(label1)
File "/home/thiago/Documents/ANU/MEDGg1/MEDG/LAWA/2014/trunk/app/models.py", line 325,   in add_label
db.session.commit()
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/scoping.py", line 150, in do
  return getattr(self.registry(), name)(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/session.py", line 776, in  commit
  self.transaction.commit()
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/session.py", line 377, in commit
  self._prepare_impl()
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/session.py", line 357, in _prepare_impl
  self.session.flush()
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/session.py", line 1919, in flush
  self._flush(objects)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/session.py", line 2037, in _flush
  transaction.rollback(_capture_exception=True)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/util/langhelpers.py", line 60, in __exit__
  compat.reraise(exc_type, exc_value, exc_tb)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/session.py", line 2001, in _flush
  flush_context.execute()
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/unitofwork.py", line 372, in execute
  rec.execute(self)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/unitofwork.py", line 526, in execute
  uow
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/persistence.py", line 65, in save_obj
  mapper, table, insert)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/persistence.py", line 570, in _emit_insert_statements
  execute(statement, multiparams)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/engine/base.py", line 729, in execute
  return meth(self, multiparams, params)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/sql/elements.py", line 321, in _execute_on_connection
  return connection._execute_clauseelement(self, multiparams, params)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/engine/base.py", line 826, in _execute_clauseelement
  compiled_sql, distilled_params
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/engine/base.py", line 958, in _execute_context
context)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/engine/base.py", line 1160, in _handle_dbapi_exception
  exc_info
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/util/compat.py", line 199, in raise_from_cause
  reraise(type(exception), exception, tb=exc_tb)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/engine/base.py", line 951, in _execute_context
context)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/engine/default.py", line 436, in do_execute
  cursor.execute(statement, parameters)
IntegrityError: (IntegrityError) UNIQUE constraint failed: blindmap.module_id u'INSERT INTO blindmap (module_id, image_id) VALUES (?, ?)' (1, 1)

更清楚地说:问题与image和blindmap之间的关系有关。我的一对一关系设置得不正确,导致了这个错误。我想知道问题出在哪里,或者如何正确地创建一对一的关系。

2 个回答

-1

试试这个

enter code here

class Image(db.Model):
    __tablename__ = 'image'
    image_id = db.Column(db.Integer, primary_key = True)
    name = db.Column(db.String(8))

class Blindmap(db.Model):
    __tablename__ = 'blindmap'
    module_id = db.Column(db.Integer, primary_key = True)
    image_id = db.Column(db.Integer, ForeignKey('image.image_id'),unique=True)
14

你的关系设置得很好。

你遇到的问题是,你自己设置了主键(在你的例子中是 module_id)。

错误信息很清楚地告诉你哪里出错了:你的数据库中已经有一个 Blindmapmodule_id = 1。因为 module_id 是你的主键,所以你不能再插入第二个相同的值。

与其自己尝试设置主键和外键,不如让 SQLAlchemy 来帮你处理这些,通过定义一个合适的关系。

比如,可以参考这个链接:

http://docs.sqlalchemy.org/en/rel_0_9/orm/relationships.html#one-to-one :

class Image(db.Model):
    __tablename__ = 'image'
    image_id = db.Column(db.Integer, primary_key = True)
    name = db.Column(db.String(8))
    # the one-to-one relation
    blindmap = relationship("Blindmap", uselist=False, backref="image")

class Blindmap(db.Model):
    __tablename__ = 'blindmap'
    module_id = db.Column(db.Integer, primary_key = True)
    image_id = db.Column(db.Integer, ForeignKey('image.image_id'))


image1 = Image(name='image1.png')
blindmap1 = Blindmap()
blindmap1.image = image1 

撰写回答