tortoise-orm
tortoise-orm copied to clipboard
Features similar to django drf source field, I don't know how to implement it
class House(Model):
id = fields.IntField(pk=True)
house_name: str = fields.CharField(max_length=255)
info: str = fields.CharField(max_length=255)
user = fields.ForeignKeyField(
"models.User",
on_delete=fields.SET_NULL,
related_name="houses",
null=True,
)
class User(Model):
id = fields.IntField(pk=True)
name: str = fields.CharField(max_length=255)
houses: fields.ReverseRelation["House"]
When I was in get User, like django's drf,
how to set the user foreign key field in the House model to a source field field,
so that it can get the name data directly from the User model?
Raw data:
{
"name": "test",
"houses": [
{
"house_name": "one",
"info": "xxxxx"
},
{
"house_name": "two",
"info": "xxxxx"
}
]
}
Expected data:
{
"name": "test",
"houses": [
{
"house_name": "one",
"info": "xxxxx",
"user": "test"
},
{
"house_name": "two",
"info": "xxxxx",
"user": "test"
}
]
}
I am pydantic beginner, I don't know how to use pydantic to define the data I want to get.
Usually, house object would be dump to {'id': 1, 'house_name': 'xx', 'info': 'xx', 'user': {'id': 1, 'name': 'test'}}
Examples:: https://github.com/tortoise/tortoise-orm/blob/develop/examples/pydantic/recursive.py https://github.com/tortoise/tortoise-orm/blob/develop/examples/pydantic/tutorial_3.py
from tortoise import Tortoise, fields, run_async
from tortoise.contrib.pydantic import pydantic_model_creator
from tortoise.models import Model
class House(Model):
id = fields.IntField(pk=True)
house_name: str = fields.CharField(max_length=255)
info: str = fields.CharField(max_length=255)
user = fields.ForeignKeyField(
"models.User",
on_delete=fields.SET_NULL,
related_name="houses",
null=True,
)
class User(Model):
id = fields.IntField(pk=True)
name: str = fields.CharField(max_length=255)
houses: fields.ReverseRelation["House"]
class PydanticMeta:
allow_cycles = True
max_recursion = 1
async def run():
await Tortoise.init(db_url="sqlite://:memory:", modules={"models": ["__main__"]})
await Tortoise.generate_schemas()
# Create object
user = await User.create(name="test")
for i in range(1, 3):
await House.create(house_name=f"house{i}", info=f"info{i}", user=user)
# Serialise it
User_Pydantic = pydantic_model_creator(User)
userpy = await User_Pydantic.from_tortoise_orm(user)
# As Python dict with Python objects (e.g. datetime)
print(userpy.model_dump())
# As serialised JSON (e.g. datetime is ISO8601 string representation)
print(userpy.model_dump_json(indent=4))
if __name__ == "__main__":
run_async(run())
Got:
{
"id": 1,
"name": "test",
"houses": [
{
"id": 1,
"house_name": "house1",
"info": "info1",
"user": {
"id": 1,
"name": "test"
}
},
{
"id": 2,
"house_name": "house2",
"info": "info2",
"user": {
"id": 1,
"name": "test"
}
}
]
}
but you can never annotate user's name to house, the only way is to select_related, btw why pydantic config exists in Model? Don't you think it break Single responsibility principle?
https://github.com/tortoise/tortoise-orm/blob/develop/examples/pydantic/recursive.py
Not working.
https://github.com/tortoise/tortoise-orm/blob/develop/examples/pydantic/recursive.py
Not working.
下面的代码可以查询出关联的blogs数据。
`from fastapi import FastAPI from tortoise.contrib.fastapi import register_tortoise from tortoise import fields, models from tortoise.fields.base import CASCADE from tortoise.query_utils import Prefetch from tortoise.contrib.pydantic import pydantic_model_creator
class User(models.Model): name = fields.CharField(max_length=32, unique=True, description='名称')
class Blog(models.Model): name = fields.CharField(max_length=32, unique=True, description='名称') user = fields.ForeignKeyField( 'models.User', on_delete=CASCADE, null=True, related_name='blogs', description='user', )
app = FastAPI()
UserSchema = pydantic_model_creator(User, name="User") BlogSchema = pydantic_model_creator(Blog, name="Blog")
class UserWithBlogsSchema(UserSchema): blogs: list[BlogSchema]
@app.get("/users/", response_model=list[UserWithBlogsSchema]) async def get_users(): users = await User.all().prefetch_related(Prefetch('blogs')) return users
register_tortoise( app, db_url="sqlite://:memory:", modules={"models": ["main"]}, generate_schemas=True, add_exception_handlers=True, )`