tortoise / tortoise/tortoise-orm

Pydantic serialisation of relations not works

Open
#548 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
5.6k
Forks
516
Avg merge
2d 21h
Merged PRs (30d)
9

Description

Describe the bug
Get TypeError: sequence item 0: expected str instance, int found when trying do PydanticModel.from_tortoise_orm(orm_instance).

File "/usr/local/lib/python3.8/site-packages/tortoise/contrib/pydantic/base.py", line 86, in from_tortoise_orm
backend_1 | await obj.fetch_related(*fetch_fields)
backend_1 | File "/usr/local/lib/python3.8/site-packages/tortoise/models.py", line 932, in fetch_related
backend_1 | await db.executor_class(model=self.class, db=db).fetch_for_list([self], *args)
backend_1 | File "/usr/local/lib/python3.8/site-packages/tortoise/backends/base/executor.py", line 559, in fetch_for_list
backend_1 | await self._execute_prefetch_queries(instance_list)
backend_1 | File "/usr/local/lib/python3.8/site-packages/tortoise/backends/base/executor.py", line 536, in _execute_prefetch_queries
backend_1 | await asyncio.gather(*prefetch_tasks)
backend_1 | File "/usr/local/lib/python3.8/site-packages/tortoise/backends/base/executor.py", line 525, in _do_prefetch
backend_1 | return await self._prefetch_direct_relation(instance_id_list, field, related_query)
backend_1 | File "/usr/local/lib/python3.8/site-packages/tortoise/backends/base/executor.py", line 486, in _prefetch_direct_relation
backend_1 | related_object_list = await related_query.filter(
backend_1 | File "/usr/local/lib/python3.8/site-packages/tortoise/queryset.py", line 803, in _execute
backend_1 | instance_list = await self._db.executor_class(
backend_1 | File "/usr/local/lib/python3.8/site-packages/tortoise/backends/base/executor.py", line 123, in execute_select
backend_1 | _, raw_results = await self.db.execute_query(query.get_sql())
backend_1 | File "/usr/local/lib/python3.8/site-packages/pypika/dialects.py", line 507, in get_sql
backend_1 | querystring = super(PostgreQueryBuilder, self).get_sql(with_alias, subquery, **kwargs)
backend_1 | File "/usr/local/lib/python3.8/site-packages/pypika/queries.py", line 1267, in get_sql
backend_1 | querystring += self._where_sql(**kwargs)
backend_1 | File "/usr/local/lib/python3.8/site-packages/pypika/queries.py", line 1394, in _where_sql
backend_1 | return " WHERE {where}".format(where=self._wheres.get_sql(quote_char=quote_char, subquery=True, **kwargs))
backend_1 | File "/usr/local/lib/python3.8/site-packages/pypika/terms.py", line 776, in get_sql
backend_1 | container=self.container.get_sql(subquery=True, **kwargs),
backend_1 | File "/usr/local/lib/python3.8/site-packages/pypika/terms.py", line 585, in get_sql
backend_1 | sql = "({})".format(",".join(term.get_sql(**kwargs) for term in self.values))
backend_1 | TypeError: sequence item 0: expected str instance, int found
backend_1 | ERROR:uvicorn.error:Exception in ASGI application
backend_1 | Traceback (most recent call last):
backend_1 | File "/usr/local/lib/python3.8/site-packages/uvicorn/protocols/http/httptools_impl.py", line 390, in run_asgi
backend_1 | result = await app(self.scope, self.receive, self.send)
backend_1 | File "/usr/local/lib/python3.8/site-packages/uvicorn/middleware/proxy_headers.py", line 45, in call
backend_1 | return await self.app(scope, receive, send)
backend_1 | File "/usr/local/lib/python3.8/site-packages/fastapi/applications.py", line 146, in call
backend_1 | await super().call(scope, receive, send)
backend_1 | File "/usr/local/lib/python3.8/site-packages/starlette/applications.py", line 102, in call
backend_1 | await self.middleware_stack(scope, receive, send)
backend_1 | File "/usr/local/lib/python3.8/site-packages/starlette/middleware/errors.py", line 181, in call
backend_1 | raise exc from None
backend_1 | File "/usr/local/lib/python3.8/site-packages/starlette/middleware/errors.py", line 159, in call
backend_1 | await self.app(scope, receive, _send)
backend_1 | File "/usr/local/lib/python3.8/site-packages/starlette/middleware/cors.py", line 76, in call
backend_1 | await self.app(scope, receive, send)
backend_1 | File "/usr/local/lib/python3.8/site-packages/starlette/exceptions.py", line 82, in call
backend_1 | raise exc from None
backend_1 | File "/usr/local/lib/python3.8/site-packages/starlette/exceptions.py", line 71, in call
backend_1 | await self.app(scope, receive, sender)
backend_1 | File "/usr/local/lib/python3.8/site-packages/starlette/routing.py", line 550, in call
backend_1 | await route.handle(scope, receive, send)
backend_1 | File "/usr/local/lib/python3.8/site-packages/starlette/routing.py", line 227, in handle
backend_1 | await self.app(scope, receive, send)
backend_1 | File "/usr/local/lib/python3.8/site-packages/starlette/routing.py", line 41, in app
backend_1 | response = await func(request)
backend_1 | File "/usr/local/lib/python3.8/site-packages/fastapi/routing.py", line 196, in app
backend_1 | raw_response = await run_endpoint_function(
backend_1 | File "/usr/local/lib/python3.8/site-packages/fastapi/routing.py", line 148, in run_endpoint_function
backend_1 | return await dependant.call(**values)
backend_1 | File "./app/router/register.py", line 27, in register
backend_1 | return await User_Pydantic.from_tortoise_orm(created_user)
backend_1 | File "/usr/local/lib/python3.8/site-packages/tortoise/contrib/pydantic/base.py", line 86, in from_tortoise_orm
backend_1 | await obj.fetch_related(*fetch_fields)
backend_1 | File "/usr/local/lib/python3.8/site-packages/tortoise/models.py", line 932, in fetch_related
backend_1 | await db.executor_class(model=self.class, db=db).fetch_for_list([self], *args)
backend_1 | File "/usr/local/lib/python3.8/site-packages/tortoise/backends/base/executor.py", line 559, in fetch_for_list
backend_1 | await self._execute_prefetch_queries(instance_list)
backend_1 | File "/usr/local/lib/python3.8/site-packages/tortoise/backends/base/executor.py", line 536, in _execute_prefetch_queries
backend_1 | await asyncio.gather(*prefetch_tasks)
backend_1 | File "/usr/local/lib/python3.8/site-packages/tortoise/backends/base/executor.py", line 525, in _do_prefetch
backend_1 | return await self._prefetch_direct_relation(instance_id_list, field, related_query)
backend_1 | File "/usr/local/lib/python3.8/site-packages/tortoise/backends/base/executor.py", line 486, in _prefetch_direct_relation
backend_1 | related_object_list = await related_query.filter(
backend_1 | File "/usr/local/lib/python3.8/site-packages/tortoise/queryset.py", line 803, in _execute
backend_1 | instance_list = await self._db.executor_class(
backend_1 | File "/usr/local/lib/python3.8/site-packages/tortoise/backends/base/executor.py", line 123, in execute_select
backend_1 | _, raw_results = await self.db.execute_query(query.get_sql())
backend_1 | File "/usr/local/lib/python3.8/site-packages/pypika/dialects.py", line 507, in get_sql
backend_1 | querystring = super(PostgreQueryBuilder, self).get_sql(with_alias, subquery, **kwargs)
backend_1 | File "/usr/local/lib/python3.8/site-packages/pypika/queries.py", line 1267, in get_sql
backend_1 | querystring += self._where_sql(**kwargs)
backend_1 | File "/usr/local/lib/python3.8/site-packages/pypika/queries.py", line 1394, in _where_sql
backend_1 | return " WHERE {where}".format(where=self._wheres.get_sql(quote_char=quote_char, subquery=True, **kwargs))
backend_1 | File "/usr/local/lib/python3.8/site-packages/pypika/terms.py", line 776, in get_sql
backend_1 | container=self.container.get_sql(subquery=True, **kwargs),
backend_1 | File "/usr/local/lib/python3.8/site-packages/pypika/terms.py", line 585, in get_sql
backend_1 | sql = "({})".format(",".join(term.get_sql(**kwargs) for term in self.values))
backend_1 | TypeError: sequence item 0: expected str instance, int found

To Reproduce

  1. Create model A
  2. Create model B with one relation to model A
  3. Tortoise.init_models(['app.models'], 'models')
  4. B_Pydantic = pydantic_model_creator(B)
  5. await B_Pydantic.from_tortoise_orm(b_instance)

Expected behavior
get related data without errors

Additional context
Add any other context about the problem here.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the two-model relation case described in the issue, then trace from tortoise/contrib/pydantic/base.py through models.py and backends/base/executor.py to the failing query generation in pypika/terms.py. Confirm that B_Pydantic.from_tortoise_orm(b_instance) fetches related data without the TypeError.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend, databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.