I m using fastapi , tortoise-orm and pydantic , everything works file except the Post method whiich contain foreign fild.
I get the error saying AttributeError: 'int' object has no attribute '_saved_in_db'
for database I am using elephantSql(postgres)
Table model
from tortoise import fields
from tortoise.models import Model
class Table(Model):
id = fields.IntField(pk=True)
name = fields.CharField(max_length=20)
Sale Model
from tortoise import fields
from tortoise.models import Model
from models.Table import Table
class Sale(Model):
id = fields.IntField(pk=True)
discount_amount = fields.FloatField(default=0)
is_draft = fields.BooleanField(default=True)
table = fields.ForeignKeyField(
"models.Table", related_name='sales', on_delete=fields.NO_ACTION)
table: fields.ForeignKeyRelation[Table] = fields.ForeignKeyField(
"models.Table", related_name="sales")
Table Schema
from typing import Optional
from pydantic import BaseModel, ValidationError
class TableIn(BaseModel):
name: str
class TableOut(BaseModel):
id: int
name: str
class TableQueryParams(BaseModel):
page: Optional[int] = 1
limit: Optional[int] = 5
name: Optional[str] = None
Sale Schema
from typing import Optional
from pydantic import BaseModel
from models.Table import Table
class SaleIn(BaseModel):
discount_amount: float
is_draft: bool
table: int
class SaleOut(BaseModel):
id: int
discount_amount: float
is_draft: bool
table: int
class SaleQueryParams(BaseModel):
page: Optional[int] = 1
limit: Optional[int] = 5
table: Optional[int] = None
Sale Route (Controller)
from fastapi import APIRouter, Depends
from typing import List
from models.Sale import Sale
from schemas.saleSchema import SaleIn, SaleOut, SaleQueryParams
saleRouter = APIRouter()
@saleRouter.post("", response_model=SaleOut)
async def create(sale: SaleIn) -> SaleOut:
# new_sale = await Sale.create(**sale.model_dump())
# return new_sale
new_sale = await Sale.create(discount_amount=sale.discount_amount, is_draft=sale.is_draft, table=sale.table)
saved_sale=new_sale.save()
return saved_sale
@saleRouter.get("", response_model=List[SaleOut])
async def get_all(query_params: SaleQueryParams = Depends()) -> List[SaleOut]:
offset = (query_params.page - 1) * query_params.limit
query = Sale.all()
if query_params.table:
query = query.filter(table__icontains=query_params.name)
sales = await query.offset(offset).limit(query_params.limit)
return list(sales)
Error:
INFO: 127.0.0.1:58776 - "POST /sales HTTP/1.1" 500 Internal Server Error
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "C:\Users\loken\AppData\Local\Programs\Python\Python311\Lib\site-packages\uvicorn\protocols\http\httptools_impl.py", line 426, in run_asgi
result = await app( # type: ignore[func-returns-value]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\loken\AppData\Local\Programs\Python\Python311\Lib\site-packages\uvicorn\middleware\proxy_headers.py", line 84, in __call__
return await self.app(scope, receive, send)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\loken\AppData\Local\Programs\Python\Python311\Lib\site-packages\fastapi\applications.py", line 292, in __call__
await super().__call__(scope, receive, send)
File "C:\Users\loken\AppData\Local\Programs\Python\Python311\Lib\site-packages\starlette\applications.py", line 122, in __call__
await self.middleware_stack(scope, receive, send)
File "C:\Users\loken\AppData\Local\Programs\Python\Python311\Lib\site-packages\starlette\middleware\errors.py", line 184, in __call__
raise exc
File "C:\Users\loken\AppData\Local\Programs\Python\Python311\Lib\site-packages\starlette\middleware\errors.py", line 162, in __call__
await self.app(scope, receive, _send)
File "C:\Users\loken\AppData\Local\Programs\Python\Python311\Lib\site-packages\starlette\middleware\exceptions.py", line 79, in __call__
raise exc
File "C:\Users\loken\AppData\Local\Programs\Python\Python311\Lib\site-packages\starlette\middleware\exceptions.py", line 68, in __call__
await self.app(scope, receive, sender)
File "C:\Users\loken\AppData\Local\Programs\Python\Python311\Lib\site-packages\fastapi\middleware\asyncexitstack.py", line 20, in __call__
raise e
File "C:\Users\loken\AppData\Local\Programs\Python\Python311\Lib\site-packages\fastapi\middleware\asyncexitstack.py", line 17, in __call__
await self.app(scope, receive, send)
File "C:\Users\loken\AppData\Local\Programs\Python\Python311\Lib\site-packages\starlette\routing.py", line 718, in __call__
await route.handle(scope, receive, send)
File "C:\Users\loken\AppData\Local\Programs\Python\Python311\Lib\site-packages\starlette\routing.py", line 276, in handle
await self.app(scope, receive, send)
File "C:\Users\loken\AppData\Local\Programs\Python\Python311\Lib\site-packages\starlette\routing.py", line 66, in app
response = await func(request)
^^^^^^^^^^^^^^^^^^^
File "C:\Users\loken\AppData\Local\Programs\Python\Python311\Lib\site-packages\fastapi\routing.py", line 273, in app
raw_response = await run_endpoint_function(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\loken\AppData\Local\Programs\Python\Python311\Lib\site-packages\fastapi\routing.py", line 190, in run_endpoint_function
return await dependant.call(**values)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\loken\Desktop\test\routes\saleRoute.py", line 13, in create
new_sale = await Sale.create(discount_amount=sale.discount_amount, is_draft=sale.is_draft, table=sale.table)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\loken\AppData\Local\Programs\Python\Python311\Lib\site-packages\tortoise\models.py", line 1133, in create
instance = cls(**kwargs)
^^^^^^^^^^^^^
File "C:\Users\loken\AppData\Local\Programs\Python\Python311\Lib\site-packages\tortoise\models.py", line 672, in __init__
for key in meta.fields.difference(self._set_kwargs(kwargs)):
^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\loken\AppData\Local\Programs\Python\Python311\Lib\site-packages\tortoise\models.py", line 687, in _set_kwargs
if value and not value._saved_in_db:
^^^^^^^^^^^^^^^^^^
AttributeError: 'int' object has no attribute '_saved_in_db'