我想我已经制定了 SQLModel 类(Alembic 确实成功创建了所有表),但我不确定从 POST 端点中的请求数据填充它们的正确方法是什么。
我有一个如下所示的请求有效负载:
{
"name": "Nicaragua",
"aka": null,
"icaoPrefix": "MN",
"continent": "North America",
"dialCode": "505",
"language": "Spanish",
"isoCode": "NI",
"isoCode3": "NIC",
"currencies": [
{"code": "NIO", "name":"Nicaraguan córdoba", "symbol":"C$"},
{"code": "USD", "name":"United States Dollar", "symbol":"$"}
],
"timezones": [
{"code": "CST", "name": "Central Standard Time", "utcOffset": -6},
{"code": "XXX", "name": "Made Up Time", "utcOffset": 7}
],
"supported": false
}
为了将其存储在数据库中,我需要使用三个模型——国家、货币和时区
我为多对多关系定义了这些模型(加上两个关联表)
class CountryCurrencyLink(SQLModel, table=True):
__table_args__ = {"schema": COUNTRY_SCHEMA}
country_uuid: Optional[str] = Field(
default=None, foreign_key=f"{COUNTRY_SCHEMA}.country.uuid", primary_key=True
)
currency_id: Optional[str] = Field(
default=None, foreign_key=f"{COUNTRY_SCHEMA}.currency.uuid", primary_key=True
)
class CurrencyBase(SQLModel):
code: Annotated[str, Field(min_length=3, max_length=3)]
name: str
symbol: str
class Currency(CurrencyBase, table=True):
__table_args__ = {"schema": COUNTRY_SCHEMA}
uuid: str = Field(default=lambda: uuid4().hex, primary_key=True)
countries: List["Country"] = Relationship(
back_populates="currencies", link_model=CountryCurrencyLink
)
class CurrencyCreate(CurrencyBase):
pass
class CountryTimezoneLink(SQLModel, table=True):
__table_args__ = {"schema": COUNTRY_SCHEMA}
country_uuid: Optional[str] = Field(
default=None, foreign_key=f"{COUNTRY_SCHEMA}.country.uuid", primary_key=True
)
timezone_id: Optional[str] = Field(
default=None, foreign_key=f"{COUNTRY_SCHEMA}.timezone.uuid", primary_key=True
)
class TimezoneBase(SQLModel):
code: Annotated[str, Field(max_length=3)]
name: str
utcOffset: conint(gt=-12, lt=13)
class Timezone(TimezoneBase, table=True):
__table_args__ = {"schema": COUNTRY_SCHEMA}
uuid: str = Field(default=lambda: uuid4().hex, primary_key=True)
countries: List["Country"] = Relationship(
back_populates="timezones", link_model=CountryTimezoneLink
)
class TimezoneCreate(TimezoneBase):
pass
class CountryBase(SQLModel):
name: str
aka: Optional[str]
icaoPrefix: Optional[str]
continent: str
dialCode: str
language: Optional[str]
isoCode: Annotated[str, Field(max_length=2)]
isoCode3: Annotated[str, Field(max_length=3)]
currencies: List[CurrencyBase]
timezones: List[TimezoneBase]
supported: bool
class Country(CountryBase, table=True):
__table_args__ = {"schema": COUNTRY_SCHEMA}
uuid: str = Field(default=uuid4().hex, primary_key=True)
currencies: List[Currency] = Relationship(
back_populates="countries", link_model=CountryCurrencyLink
)
timezones: List[Timezone] = Relationship(
back_populates="countries", link_model=CountryTimezoneLink
)
class CountryCreate(CountryBase):
pass
class CountryRead(CountryBase):
pass
但我的问题是如何处理 POST 请求并创建类和关系。
我试过这个:
@router.post("/")
async def create_country(
*, session: AsyncSession = Depends(get_session), country: CountryCreate
):
db_country = Country.from_orm(country)
session.add(db_country)
await session.commit()
await session.refresh(db_country)
return db_country
我希望from_orm
可能已经处理了它,但它看起来不像。我不确定我是否应该采取天真的方法并手动创建它们?或者也许我需要重组我的课程?或者也许有推荐的方法来解决这个问题?
任何帮助表示赞赏!
更新
我试过天真地创造它
@router.post("/")
async def create_country(
*, session: AsyncSession = Depends(get_session), country: CountryCreate
):
db_country = Country(
name=country.name,
icaoPrefix=country.icaoPrefix,
continent=country.continent,
dialCode=country.dialCode,
language=country.language,
isoCode=country.isoCode,
isoCode3=country.isoCode3,
supported=country.supported,
)
db_country.currencies = country.currencies
但是最后一行导致了这个错误
'CurrencyBase' object has no attribute '_sa_instance_state'