itsource

FastAPI + SQLAlchemy - datetime 필드가 있는 테이블에 항목을 게시할 때 잘못된 RequestError가 발생함

mycopycode 2023. 6. 26. 21:18
반응형

FastAPI + SQLAlchemy - datetime 필드가 있는 테이블에 항목을 게시할 때 잘못된 RequestError가 발생함

여기서는 로컬 MariaDB를 데이터베이스로 사용하여 FastAPI 설명서의 전체 SQLChemy 부분을 작성했습니다.

제가 가지고 있는 코드는 마지막에 나열된 최종 파일과 동일하게 보입니다.저는 모든 것을 테스트했고 모든 것이 작동합니다.

DHT(Digital Humidity and Temperature)라는 자체 데이터베이스 테이블을 만들려다가 문제가 발생했습니다.이것은 낮 동안 특정 시간에 제 방의 습도와 온도에 대한 정보를 저장하기 위한 것입니다.테이블에 쓰기 위해 엔드포인트를 테스트할 때 오류가 반환됩니다.그러나 데이터는 아래 그림과 같이 테이블에 저장됩니다.

SQL 화학 ORM 모델은 다음과 같습니다.

class DHT(Base):
    __tablename__ = "dht"

    datetime = Column(DateTime, primary_key=True, default=datetime.now)
    humidity = Column(Float(8), index=True)
    temp = Column(Float(8), index=True)

다음은 데이터 검증을 위한 Pydantic 스키마입니다.

class DHTBase(BaseModel):
    temp: float
    humidity: float

class DHTCreate(DHTBase):
    pass

class DHT(DHTBase):
    """
    In the Pydantic models for reading, we add an internal Config class.
    """
    date: datetime

    class Config:
        orm_mode = True

모든 것은 여기 엔드포인트에서 시작합니다. 저는 가능한 한 다른 POST 엔드포인트 예제를 따릅니다.

@app.post("/dht/", response_model=schemas.DHT)
def create_dht(dht: schemas.DHTCreate,
               db: Session = Depends(get_db)):
    return crud.create_dht(db=db, dht_data=dht)

엔드포인트에서 호출하는 crud 작업은 다음과 같습니다.

def create_dht(db: Session, dht_data: schemas.DHTCreate):

    dht = models.DHT(humidity=dht_data.humidity,
                     temp=dht_data.temp)
    db.add(dht)
    db.commit()
    db.refresh(dht)
    return dht

엔드포인트를 컬로 테스트할 때 다음과 같은 예가 있습니다.

curl -X 'POST' \
  'http://127.0.0.1:8000/dht/' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "temp": 23.34,
  "humidity": 55.35
}'

...FastAPI가 다음 오류를 기록합니다.

  File "/home/sydney/.cache/pypoetry/virtualenvs/app-sfi98_Li-py3.10/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 2328, in refresh
    raise sa_exc.InvalidRequestError(
sqlalchemy.exc.InvalidRequestError: Could not refresh instance '<DHT at 0x7f09f52c5420>'

하지만 제가 데이터베이스를 확인했을 때, 항목이 실제로 작성되어 있습니다.

MariaDB [blogfolio]> select * from dht;
+---------------------+----------+-------+
| datetime            | humidity | temp  |
+---------------------+----------+-------+
| 2022-03-26 10:00:11 |    55.35 | 23.34 |
+---------------------+----------+-------+

제가 FastAPI에서 예상한 답변은 이 양식의 JSON일 것입니다.

{
  "temp": 23.34,
  "humidity": 55.35,
  "date": "2022-03-26T17:00:11.815Z"
}

대신 "내부 서버 오류"가 표시됩니다.

저는 DHT 테이블의 더미 버전을 만들었는데, datetime 열은 문자열 열로 대체되고 문자열 데이터로 채워져 있고, 모든 것이 잘 작동합니다.이 시점에서 제가 유일하게 확신하는 것은 SQL Chemy에서 가져온 것이라는 것입니다. 이는 ORM 모델의 날짜 필드나 날짜 데이터를 어떻게 작성하는지를 좋아하지 않습니다.

ORM 모델/CRUD 작동에 문제가 있습니까?

mariadb의 datetime에 대한 설명서에는 0마이크로초가 기본 datetime 정밀도라고 나와 있습니다.이것은 당신의 db 출력에서 그렇게 보입니다. 2022-03-26 10:00:11또한 동일한 설명서에서 표준 시간대는 세션에 따라 달라집니다.

다음을 사용하여 이 예외와 반 수정을 다시 생성할 수 있었습니다.DATETIME(fsp=6)다음과 같은 상황이 발생합니다.

  1. DHT는 파이썬의datetime.now()응용 프로그램의 기본 키로
  2. DHT는 DB에 기록됩니다. 기본적으로 열에 마이크로초가 없을 것으로 예상되므로 mariadb에서 마이크로초가 무시될 수 있습니다.
  3. 를 실행하여 "" "SQL" "DB"로.datetime = 2022-03-26T17:00:11.815마이크로초)
  4. 그것은 그것을 찾을 수 없습니다 왜냐하면datetimedb에서 그것들을 아래로 자릅니다.2022-03-26T17:00:11합니다.

여기서 가장 안전한 방법은 기본 키에 정수 ID를 사용하는 것입니다. 하지만...

이 작업을 먼저 수행하려면 컬럼의 정밀도를 마이크로초 동안 6자리까지 올릴 수 있습니다. 특유의 것을 해야 합니다.DATETIME,from sqlalchemy.dialect.mysql import DATETIME,와 함께fsp=6.

그럼 시간대는...mariadb는 변환을 하지 않기 때문에 앱에서 날짜 시간을 만들기 위해 사용하는 시간대와 DB 세션 시간대가 일치하는지 확인해야 합니다.UTC가 여기서 가장 안전할 것 같은데 mariadb의 세부 사항은 잘 모르겠습니다.

서버의 기본값 자체를 변경해야 할 수도 있습니다.세에효수있습다니있을에 효과가 있을 수 .session.execute(text("SET time_zone = 'UTC'")).

파이썬에서 당신은 할 수 있었습니다.default = lambda: datetime.datetime.now(datetime.timezone.utc).replace(tzinfo=None)경유로import datetime이렇게 하면 현재 시간이 UTC로 표시되지만 시간대가 제거되어 dt가 단순해집니다.

언급URL : https://stackoverflow.com/questions/71630320/fastapi-sqlalchemy-invalidrequesterror-when-posting-entry-to-table-with-date

반응형