tortoise / tortoise/tortoise-orm
AttributeError: 'int' object has no attribute '_saved_in_db' , Fastapi , Tortoise-orm , pydantic
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 5.6k
- Forks
- 516
- Avg merge
- 2d 21h
- Merged PRs (30d)
- 9
Description
I m using fastapi , tortoise-orm and pydantic , everything works fine except the Post method which contain foreign key field.
I get the error saying AttributeError: 'int' object has no attribute '_saved_in_db'
for database I am using elephantSql(postgres)
Repo : https://github.com/lokendra-chaulagain/object-has-no-attribute-in-db-issue
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(
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
The relevant entry point is the Sale POST route, with the Sale model and SaleIn/SaleOut schemas shown in the issue. Reproduce POST /sales with a foreign-key table value and inspect the complete traceback, then compare the create/save flow with the expected response. Done means the request completes without AttributeError and returns the documented SaleOut shape.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- fastapi, postgresql, python
- Domain
- api, backend, database
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100