【问题标题】:FastAPI / sqlite3.InterfaceError: Error binding parameter 0 - probably unsupported typeFastAPI / sqlite3.InterfaceError: Error binding parameter 0 - 可能是不支持的类型
【发布时间】:2020-05-03 17:53:08
【问题描述】:

我需要创建一个端点,允许我编辑客户数据(公司、地址、城市、州、国家、邮政编码、传真 - 不是所有 .schema 客户字段)。端点必须能够接受具有以下字段的 json 对象。我需要确保具有给定 id 的客户端存在于 clients 表中。作为响应,代码为 200 的应用程序将返回客户的对象。我遇到了这个我无法解决的恼人错误。这是我的功能:

import aiosqlite
from fastapi import APIRouter, Response, status
from pydantic import BaseModel

class Customer(BaseModel):
    company: str = None
    address: str = None
    city: str = None
    state: str = None
    country: str = None
    postalcode: str = None
    fax: str = None

router = APIRouter()
@router.on_event("startup")
async def startup():
    router.db_connection = await aiosqlite.connect('chinook.db')


@router.on_event("shutdown")
async def shutdown():
    await router.db_connection.close()

@router.put("/customers/{customer_id}")
async def update_customer(response: Response, customer_id: int, customer: Customer):
    cursor = await router.db_connection.execute(
        "SELECT CustomerId FROM customers WHERE CustomerId = ?", (customer_id, )
    )
    customer_id = await cursor.fetchone()
    if not customer_id:
        response.status_code = status.HTTP_404_NOT_FOUND
        return {"detail": {"error": "No customer found with the given customer_id!"}}
    update_date = customer.dict(exclude_unset=True)
    if update_date:
        sql = "UPDATE customers SET "
        for key, value in update_date.items():
            if key == "postalcode":
                key = "PostalCode"
            key = key.capitalize()
            sql += f"{key} = '{value}', "
        sql = sql[:-2] + f" WHERE CustomerId = {customer_id}"
        cursor = await router.db_connection.execute(sql)
        await router.db_connection.commit()
    router.db_connection.row_factory = aiosqlite.Row
    cursor = await router.db_connection.execute(
        "SELECT * FROM customers WHERE CustomerId = ?", (customer_id, )
    )
    customer = await cursor.fetchone()
    return customer


sqlite> .schema customers
CREATE TABLE IF NOT EXISTS "customers"
(
    [CustomerId] INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
    [FirstName] NVARCHAR(40)  NOT NULL,
    [LastName] NVARCHAR(20)  NOT NULL,
    [Company] NVARCHAR(80),
    [Address] NVARCHAR(70),
    [City] NVARCHAR(40),
    [State] NVARCHAR(40),
    [Country] NVARCHAR(40),
    [PostalCode] NVARCHAR(10),
    [Phone] NVARCHAR(24),
    [Fax] NVARCHAR(24),
    [Email] NVARCHAR(60)  NOT NULL,
    [SupportRepId] INTEGER,
    FOREIGN KEY ([SupportRepId]) REFERENCES "employees" ([EmployeeId]) 
                ON DELETE NO ACTION ON UPDATE NO ACTION
);
CREATE INDEX [IFK_CustomerSupportRepId] ON "customers" ([SupportRepId]);
sqlite> 


错误如下所示:


INFO:     127.0.0.1:49752 - "PUT /customers/1 HTTP/1.1" 500 Internal Server Error
ERROR:    Exception in ASGI application
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/uvicorn/protocols/http/httptools_impl.py", line 385, in run_asgi
    result = await app(self.scope, self.receive, self.send)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/uvicorn/middleware/proxy_headers.py", line 45, in __call__
    return await self.app(scope, receive, send)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/fastapi/applications.py", line 149, in __call__
    await super().__call__(scope, receive, send)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starlette/applications.py", line 102, in __call__
    await self.middleware_stack(scope, receive, send)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starlette/middleware/errors.py", line 181, in __call__
    raise exc from None
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starlette/middleware/errors.py", line 159, in __call__
    await self.app(scope, receive, _send)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starlette/exceptions.py", line 82, in __call__
    raise exc from None
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starlette/exceptions.py", line 71, in __call__
    await self.app(scope, receive, sender)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starlette/routing.py", line 550, in __call__
    await route.handle(scope, receive, send)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starlette/routing.py", line 227, in handle
    await self.app(scope, receive, send)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starlette/routing.py", line 41, in app
    response = await func(request)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/fastapi/routing.py", line 165, in app
    raw_response = await run_endpoint_function(
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/fastapi/routing.py", line 119, in run_endpoint_function
    return await dependant.call(**values)
  File "./routers/tracks.py", line 109, in update_customer
    cursor = await router.db_connection.execute(
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/aiosqlite/core.py", line 209, in execute
    cursor = await self._execute(self._conn.execute, sql, parameters)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/aiosqlite/core.py", line 167, in _execute
    return await future
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/aiosqlite/core.py", line 153, in run
    result = function()
sqlite3.InterfaceError: Error binding parameter 0 - probably unsupported type.

请帮帮我,我是初学者。

【问题讨论】:

  • 你能不能从命令行连接到你的数据库并显示.schema customers的输出
  • @Tom Carrick 我在代码下添加了 .schema 客户,因为在评论中我对字符数有限制。

标签: python sqlite fastapi


【解决方案1】:

我认为问题出在这段代码中:

    cursor = await router.db_connection.execute(
        "SELECT CustomerId FROM customers WHERE CustomerId = ?", (customer_id, )
    )
    customer_id = await cursor.fetchone()
    if not customer_id:
        response.status_code = status.HTTP_404_NOT_FOUND
        return {"detail": {"error": "No customer found with the given customer_id!"}}

cursor.fetchone() 返回一行,而不是单个值,因此本节将变量 customer_id 中的值类型从 int 更改为一行。*

您可能想要做的是在检查现有客户时使用另一个变量。这使customer_id 保持原样。我在下面的两行中使用了customer_row 作为这个新变量。它不需要在其他任何地方使用:如果我们从这个游标中返回一行,它包含的唯一值将是我们已经拥有的客户 ID:

    cursor = await router.db_connection.execute(
        "SELECT CustomerId FROM customers WHERE CustomerId = ?", (customer_id, )
    )
    customer_row = await cursor.fetchone()
    if not customer_row:
        response.status_code = status.HTTP_404_NOT_FOUND
        return {"detail": {"error": "No customer found with the given customer_id!"}}

* 我故意对上面“行”的确切含义有点模糊。根据aiosqlite documentationcursor.fetchone() 返回一个可选的sqlite3.Row,但是当我运行这段代码时,它返回了一个元组。我不确定这是否会产生巨大的差异:关键是Rows 和元组都不是ints。

【讨论】:

  • 非常感谢您!你帮我解决了一个问题! :) :) :)
猜你喜欢
  • 2021-05-07
  • 2013-11-17
  • 1970-01-01
  • 2021-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-24
相关资源
最近更新 更多