Mark Wardell
Mark Wardell

Reputation: 555

SqlModel datetime field is throwing error upon execution

I am using SQLModel in python 3.8

When I add my datetime field created_at: datetime = Field(default_factory=utcnow(), nullable=False)

I get this Error

File "./app/main.py", line 16, in <module>
    class Post(SQLModel, table=True):
  File "/Users/markwardell/PycharmProjects/pythonProject/venv/lib/python3.8/site-packages/sqlmodel/main.py", line 277, in __new__
    new_cls = super().__new__(cls, name, bases, dict_used, **config_kwargs)
  File "pydantic/main.py", line 204, in pydantic.main.ModelMetaclass.__new__
  File "pydantic/fields.py", line 488, in pydantic.fields.ModelField.infer
  File "pydantic/fields.py", line 419, in pydantic.fields.ModelField.__init__
  File "pydantic/fields.py", line 539, in pydantic.fields.ModelField.prepare
  File "pydantic/fields.py", line 801, in pydantic.fields.ModelField.populate_validators
  File "pydantic/validators.py", line 718, in find_validators
RuntimeError: error checking inheritance of <module 'datetime' from '/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/datetime.py'> (type: module)

If I do not the add the created_at the table is created in PostgresSql as expected. Code

import datetime
from typing import Optional
import utcnow as utcnow
from fastapi import FastAPI
from sqlalchemy import TIMESTAMP, text
from sqlmodel import Field, Session, SQLModel, create_engine, select
from app.database import SQLALCHEMY_DATABASE_URL

class Hero(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str = Field(index=True)
    secret_name: str
    age: Optional[int] = Field(default=None, index=True)


class Post(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True, nullable=False)
    title: str = Field(nullable=False)
    content: str = Field(nullable=False)
    published: bool = Field(default=True, nullable=False)
    created_at: datetime = Field(default_factory=utcnow(), nullable=False)

engine = create_engine(SQLALCHEMY_DATABASE_URL)


def create_db_and_tables():
    SQLModel.metadata.create_all(engine)


app = FastAPI()


@app.on_event("startup")
def on_startup():
    create_db_and_tables()

Upvotes: 4

Views: 12667

Answers (2)

Dariosky
Dariosky

Reputation: 531

Also, note that your code should be

created_at: datetime.datetime = Field(default_factory=datetime.utcnow, nullable=False)

without calling utcnow on instantiation, doing so will give every entry datetime as consulted at instantiation. Thus, default_factory should be the function, not the value.

Upvotes: 13

John Kealy
John Kealy

Reputation: 1883

This was explained in a comment, but just to add it as an answer for others:

You must import datetime like this

from datetime import datetime

The datetime we require in this context is a actually a class inside a module that is also called datetime.

Upvotes: 12

Related Questions