【发布时间】:2020-12-22 21:08:59
【问题描述】:
我在开发过程中使用 SQLAlchemy 在本地查询 SQLite 数据库的 Flask 应用程序中有订阅和订阅者表/模型的简单关系。
订阅通过如下定义的subscriber_id 字段与订阅者建立关系:
subscriber_id = Column(db.Integer, ForeignKey('subscriber.id'))
这两个对象都有一个定义为String(36) 的字段,当它们在数据库中创建时,我将在其中写入一个 UUID4 字符串。它们分别是subscription_id 和subscriber_id,像这样:
@dataclass
class Subscription(db.Model):
__tablename__ = 'subscription'
subscription: str
subscriber: str
id = Column(db.Integer, primary_key=True)
subscription_id = Column(
db.String(36),
default=generate_uuid, # a function that returns a uuid4
unique=True
)
subscriber_id = Column(db.Integer, ForeignKey('subscriber.id'))
在使用 PyTest 执行测试期间,我遇到了一个奇怪的行为,其中 Subscription 实例的 subscriber_id 返回的不是类中定义的整数,而是一个 UUID。
测试运行一个查询订阅者的方法,然后尝试获取其订阅:
subscriber = Subscriber.query.filter(
Subscriber.subscriber_id == subscriber_id
).first()
assert subscriber is not None
subscriptions = Subscription.query.filter(
Subscription.subscriber_id == subscriber_id
).all()
subscriber_id在执行期间是1,从数据库中检索订阅者。
然而,第二个查询不起作用,即使 subscriber_id 是订阅者的 id 的外键。
如果我用另一个不带过滤器的查询替换第二个查询,它可以工作。但是后来我看到了这个问题,返回的subscriber_id 不是整数,而是 UUID:
raise Exception(Subscription.query.first().subscriber_id)
subscriptions = Subscription.query.filter(
Subscription.subscriber_id == subscriber_id
).all()
> raise Exception(Subscription.query.first().subscriber_id)
E Exception: 59ebfdd6-1cbc-4748-94e1-955ef55c380c
我在这里没有考虑到 SQLAlchemy 的特殊行为吗?可能是表/字段的命名约定?
【问题讨论】:
-
Subscription.id已经是主键。候选键Subscription.subscription_id的用途是什么? -
另外,检查你的工作。
subscriber_id不会返回 uuid,但subscription_id会。这里没有命名约定。 -
@GordThompson 目的不是在请求 URI 或正文中显示实际 ID,因为它是一个 API。这是一种替代ID。我计划在内部调用中使用实际的
id。我会用更多信息更新原始帖子。 -
哦等等,这是 SQLite。你有explicitly enabled foreign key support吗?
-
@GordThompson 这真的很奇怪。当显式启用外键支持时,我得到一个 IntegrityException。
标签: python unit-testing sqlalchemy pytest