我有一个包含点和对象概念的数据库。对象以一对一的关系与单个点相关联。一次只能有一个对象与一个点相关联,我通过唯一性约束强制执行了这一点。
但是,我总是想说对象只能与存在的点相关联,但我正在努力了解如何实现这一点。
在我进一步解释之前,这是我拥有的一些测试代码:
import sqlalchemy as sql
import sqlalchemy.orm as sqlorm
import sqlalchemy.ext.declarative
import os
debug = True
db_file = "/".join([os.getcwd() if __name__ == "__main__" else os.path.dirname(__file__), 'sqlite.db'])
engine_opts = {
'echo': debug
}
engine = sql.create_engine('sqlite:///{}'.format(db_file), **engine_opts)
Session = sqlorm.sessionmaker(bind=engine)
Base = sqlalchemy.ext.declarative.declarative_base()
class Point(Base):
__tablename__ = 'point'
x = sql.Column(sql.Integer, primary_key=True, nullable=False)
y = sql.Column(sql.Integer, primary_key=True, nullable=False)
def __repr__(self):
return self.__str__()
def __str__(self):
return "({x},{y})".format(x=self.x, y=self.y)
def __unicode__(self):
return self.__str__()
class Obj(Base):
__tablename__ = 'obj'
id = sql.Column(sql.Integer, primary_key=True)
x = sql.Column(sql.Integer)
y = sql.Column(sql.Integer)
__table_args__ = (
sql.ForeignKeyConstraint([x, y], [Point.x, Point.y]),
sql.UniqueConstraint(x, y, name='obj_coords'),
)
point = sqlorm.relationship("Point", backref=sqlorm.backref('obj', uselist=False))
def init_db():
Base.metadata.create_all(engine)
session = Session()
min_val = 0
max_val = 20
for x in range(min_val, max_val):
for y in range(min_val, max_val):
session.add(Point(x=x, y=y))
session.commit()
session.add(Obj(x=0, y=0))
session.add(Obj(x=10, y= 10))
session.add(Obj(x=-1, y=-1))
session.commit()
session.close()
def reinit_db():
Base.metadata.drop_all(engine)
init_db()
if __name__ == "__main__":
reinit_db()
我有一个复合主键Point
,我想使用x
和作为外键y
。Obj
作品和backref
唯一性约束意味着没有 2 个 objs 可以占据同一点,但是我的测试代码允许我Obj
在不存在的Point
(-1, -1) 中创建一个,当我想要阻止它时。
这有可能实现吗,我该怎么做?