sqlalchemy + postgres asyncpg.exceptions.ForeignKeyViolationError on relationship()
Posted
技术标签:
【中文标题】sqlalchemy + postgres asyncpg.exceptions.ForeignKeyViolationError on relationship()【英文标题】: 【发布时间】:2022-01-03 21:55:45 【问题描述】:到目前为止,在我的项目中,我正在制作原型并将 sqlite 与 sqlalchemy 一起使用。
我有几个具有 oneToMany 关系的表,一切都很好。
现在,在切换到 postgres 后,我得到了我定义 ForeignKeys 的表的asyncpg.exceptions.ForeignKeyViolationError
。
这是我的 sqlalchemy 父子模型:
from sqlalchemy.orm import relationship
from .database import Base
from fastapi_users_db_sqlalchemy import SQLAlchemyBaseUserTable
class Company(Base):
__tablename__ = "company"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, unique=True)
type = Column(
String(length=10),
server_default="No type given",
nullable=False,
)
users = relationship("User", back_populates="company")
class User(Base, SQLAlchemyBaseUserTable):
first_name = Column(
String(length=50),
index=True,
server_default="No name given",
nullable=False,
)
company_id = Column(Integer, ForeignKey("company.id"), nullable=False)
company = relationship("Company", back_populates="users")
尝试注册用户时,我得到:
INFO: 172.17.0.1:63534 - "POST /auth/register HTTP/1.1" 500 Internal Server Error
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "/usr/lib/python3.9/site-packages/uvicorn/protocols/http/h11_impl.py", line 373, in run_asgi
result = await app(self.scope, self.receive, self.send)
File "/usr/lib/python3.9/site-packages/uvicorn/middleware/proxy_headers.py", line 75, in __call__
return await self.app(scope, receive, send)
File "/usr/lib/python3.9/site-packages/fastapi/applications.py", line 208, in __call__
await super().__call__(scope, receive, send)
File "/usr/lib/python3.9/site-packages/starlette/applications.py", line 112, in __call__
await self.middleware_stack(scope, receive, send)
File "/usr/lib/python3.9/site-packages/starlette/middleware/errors.py", line 181, in __call__
raise exc
File "/usr/lib/python3.9/site-packages/starlette/middleware/errors.py", line 159, in __call__
await self.app(scope, receive, _send)
File "/usr/lib/python3.9/site-packages/starlette/middleware/cors.py", line 92, in __call__
await self.simple_response(scope, receive, send, request_headers=headers)
File "/usr/lib/python3.9/site-packages/starlette/middleware/cors.py", line 147, in simple_response
await self.app(scope, receive, send)
File "/usr/lib/python3.9/site-packages/starlette/exceptions.py", line 82, in __call__
raise exc
File "/usr/lib/python3.9/site-packages/starlette/exceptions.py", line 71, in __call__
await self.app(scope, receive, sender)
File "/usr/lib/python3.9/site-packages/starlette/routing.py", line 656, in __call__
await route.handle(scope, receive, send)
File "/usr/lib/python3.9/site-packages/starlette/routing.py", line 259, in handle
await self.app(scope, receive, send)
File "/usr/lib/python3.9/site-packages/starlette/routing.py", line 61, in app
response = await func(request)
File "/usr/lib/python3.9/site-packages/fastapi/routing.py", line 226, in app
raw_response = await run_endpoint_function(
File "/usr/lib/python3.9/site-packages/fastapi/routing.py", line 159, in run_endpoint_function
return await dependant.call(**values)
File "/usr/lib/python3.9/site-packages/fastapi_users/router/register.py", line 32, in register
created_user = await user_manager.create(user, safe=True, request=request)
File "/usr/lib/python3.9/site-packages/fastapi_users/manager.py", line 153, in create
created_user = await self.user_db.create(db_user)
File "/usr/lib/python3.9/site-packages/fastapi_users_db_sqlalchemy/__init__.py", line 159, in create
await self.database.execute(query, user_dict)
File "/usr/lib/python3.9/site-packages/databases/core.py", line 169, in execute
return await connection.execute(query, values)
File "/usr/lib/python3.9/site-packages/databases/core.py", line 295, in execute
return await self._connection.execute(built_query)
File "/usr/lib/python3.9/site-packages/databases/backends/postgres.py", line 210, in execute
return await self._connection.fetchval(query_str, *args)
File "/usr/lib/python3.9/site-packages/asyncpg/connection.py", line 645, in fetchval
data = await self._execute(query, args, 1, timeout)
File "/usr/lib/python3.9/site-packages/asyncpg/connection.py", line 1659, in _execute
result, _ = await self.__execute(
File "/usr/lib/python3.9/site-packages/asyncpg/connection.py", line 1684, in __execute
return await self._do_execute(
File "/usr/lib/python3.9/site-packages/asyncpg/connection.py", line 1731, in _do_execute
result = await executor(stmt, None)
File "asyncpg/protocol/protocol.pyx", line 201, in bind_execute
asyncpg.exceptions.ForeignKeyViolationError: insert or update on table "user" violates foreign key constraint "user_company_id_fkey"
DETAIL: Key (company_id)=(1) is not present in table "company".
错误是正确的,表company_id
中没有列company
- 只有id
。
我定义为user
表中的company_id
列使用值company.id
。
为什么程序会检查company_id
?
我按照这个 sqlalchemy 文档来定义关系:https://docs.sqlalchemy.org/en/14/orm/basic_relationships.html 使用 sqlite 可以正常工作。
我可以在回溯中看到,它连接到正确的后端 (postgres
),这是否意味着 sqlalchemy 没有以正确的方式为 postgres 转换关系?
有什么办法解决这个问题吗?
【问题讨论】:
【参考方案1】:已解决 - 也适用于遇到此问题的任何人:
postgres 似乎不像 sqlite 那样重置 id-counter。由于我在脚本中创建了测试数据,总是从 1 开始直到范围限制,所以我使用了不再存在的 ids
。
举个例子:我用来创建新用户的company_id
显然已经不存在了。
这个,我偶然发现的。错误信息完全误导了我。
【讨论】:
以上是关于sqlalchemy + postgres asyncpg.exceptions.ForeignKeyViolationError on relationship()的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Postgres 在 SQLAlchemy 中创建表?
Flask 和 Heroku sqlalchemy.exc.NoSuchModuleError:无法加载插件:sqlalchemy.dialects:postgres
在 Postgres 上使用 sqlalchemy 创建部分唯一索引
Postgres中'money'和'OID'的sqlalchemy等效列类型是啥?