在Tortoise-ORM+FastAPI中未显示模型关系 [英] Model Relationships not showing in Tortoise-ORM + FastAPI
本文介绍了在Tortoise-ORM+FastAPI中未显示模型关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我使用Tortoise-ORM来处理FastAPI的orm时遇到了一个问题。具体地说,我无法在模型中返回关系。
这是我的应用程序结构。结构的灵感来自Django的应用程序结构。
.
├── Dockerfile
├── LICENSE
├── Pipfile
├── Pipfile.lock
├── README.md
├── app
│ ├── contacts
│ │ ├── __init__.py
│ │ ├── main.py
│ │ ├── models.py
│ │ └── routers.py
│ ├── main.py
│ ├── resources
│ │ ├── __init__.py
│ │ ├── constants.py
│ │ ├── core_model.py
│ │ ├── database.py
│ │ └── middlewares.py
│ └── users
│ ├── __init__.py
│ ├── main.py
│ ├── models.py
│ └── routers.py
└── docker-compose.yml
在app/resources/database.py
中设置数据库连接如下;
from fastapi import FastAPI
from tortoise.contrib.fastapi import register_tortoise
def get_db_uri(*, user, password, host, db):
return f'postgres://{user}:{password}@{host}:5432/{db}'
def setup_database(app: FastAPI):
register_tortoise(
app,
db_url=get_db_uri(
user='postgres',
password='postgres',
host='db', # docker-compose service name
db='postgres',
),
modules={
'models': [
'app.users.models',
'app.contacts.models',
],
},
generate_schemas=True,
add_exception_handlers=True,
)
从models
参数可以看到设置了两个模型。这里有两个。
APP/USERS/Models.py
from tortoise import Tortoise, fields
from tortoise.contrib.pydantic import pydantic_model_creator
from passlib.hash import bcrypt
from app.resources.core_model import CoreModel
class User(CoreModel):
username = fields.CharField(50, unique=True)
email = fields.CharField(60, unique=True)
password_hash = fields.CharField(128)
def __str__(self):
return self.email
def verify_password(self, password):
return bcrypt.verify(password, self.password_hash)
class PydanticMeta:
exclude = ["password_hash"]
# Tortoise.init_models(['app.users.models'], 'models')
User_Pydantic = pydantic_model_creator(User, name='User')
UserIn_Pydantic = pydantic_model_creator(
User, name='UserIn', exclude_readonly=True)
应用程序/联系人/模型.py
from tortoise import Tortoise, fields
from tortoise.contrib.pydantic import pydantic_model_creator
from app.resources.core_model import CoreModel
class Contact(CoreModel):
user = fields.ForeignKeyField(
'models.User', related_name='contacts')
name = fields.CharField(50)
def __str__(self):
return self.name
# Tortoise.init_models(['app.users'], 'models')
Contact_Pydantic = pydantic_model_creator(Contact, name='Contact')
ContactIn_Pydantic = pydantic_model_creator(
Contact, name='ContactIn', exclude_readonly=True)
以下是用户尝试保存联系人时发生的情况。
@router.post('/', status_code=status.HTTP_201_CREATED)
async def create_contact(contact_name: str = Form(...), user: User_Pydantic = Depends(get_current_user)):
try:
contact = Contact(user_id=user.id, name=contact_name)
await contact.save()
contact_obj = await Contact_Pydantic.from_tortoise_orm(contact)
print(contact_obj.schema_json(indent=4))
except Exception as err:
print(err)
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST, detail='failed to save data')
return {'status_code': status.HTTP_201_CREATED, 'contact': contact_obj.dict()}
用户可以从以下路线检索其保存的联系人。
@router.get('/me')
async def get_all_contacts(user: User_Pydantic = Depends(get_current_user)):
try:
contacts = await Contact.filter(user_id=user.id)
contacts_list = [await Contact_Pydantic.from_tortoise_orm(contact) for contact in contacts]
print(user.schema_json())
except:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST, detail='failed to fetch related data')
return {'contacts': contacts_list}
当用户检索他们的联系人时,它不会显示与用户的关系。在本例中,这不是必需的,但我想弄清楚如何获取响应中的关系以供将来参考。
我浏览了文档,发现early-init是一个东西,并尝试使用init_models
,但似乎不起作用。或许我只是不知道它是怎么运作的。如果我需要使用init_models
,令人困惑的部分是1.何时调用它和2.如何调用它。init_models
两个论点把我搞糊涂了。
作为总结,我有两个问题。
- 如何从模型获取关系并将其返回给用户。
- 如果我需要使用
init_models
,我应该在哪里调用它,并且使用此应用程序结构,2个必需参数的正确方式是什么。
提前谢谢您。
注意:
- 我尝试了以下方法来保存联系人,但结果相同。
@router.post('/', status_code=status.HTTP_201_CREATED)
async def create_contact(contact_name: str = Form(...), user: User_Pydantic = Depends(get_current_user)):
try:
user = await User.get(id=user.id)
contact = await Contact.create(user=user, name=contact_name)
contact_obj = await Contact_Pydantic.from_tortoise_orm(contact)
print(contact_obj.schema_json(indent=4))
except Exception as err:
print(err)
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST, detail='failed to save data')
return {'status_code': status.HTTP_201_CREATED, 'contact': contact_obj.dict()}
推荐答案
多亏了@alex_noame,我才能做到这一点。
首先,从Models.py中分离出简单的模式。
.
├── Dockerfile
├── LICENSE
├── Pipfile
├── Pipfile.lock
├── README.md
├── app
│ ├── contacts
│ │ ├── __init__.py
│ │ ├── main.py
│ │ ├── models.py
│ │ ├── routers.py
│ │ └── schemas.py <- new
│ ├── main.py
│ ├── resources
│ │ ├── __init__.py
│ │ ├── constants.py
│ │ ├── core_model.py
│ │ ├── database.py
│ │ └── middlewares.py
│ └── users
│ ├── __init__.py
│ ├── main.py
│ ├── models.py
│ ├── routers.py
│ └── schemas.py <- new
└── docker-compose.yml
app/USERS/schemas.py
from tortoise.contrib.pydantic import pydantic_model_creator
from .models import User
User_Pydantic = pydantic_model_creator(User, name='User')
UserIn_Pydantic = pydantic_model_creator(
User, name='UserIn', exclude_readonly=True)
应用程序/联系人/方案.py
from tortoise.contrib.pydantic import pydantic_model_creator
from .models import Contact
Contact_Pydantic = pydantic_model_creator(Contact, name='Contact')
ContactIn_Pydantic = pydantic_model_creator(
Contact, name='ContactIn', exclude_readonly=True)
然后,在我们要设置乌龟orm的app/Resources/datase.py中,调用init_models
。
from fastapi import FastAPI
from tortoise import Tortoise
from tortoise.contrib.fastapi import register_tortoise
def get_db_uri(*, user, password, host, db):
return f'postgres://{user}:{password}@{host}:5432/{db}'
def setup_database(app: FastAPI):
register_tortoise(
app,
db_url=get_db_uri(
user='postgres',
password='postgres',
host='db', # docker-composeのservice名
db='postgres',
),
modules={
'models': [
'app.users.models',
'app.contacts.models',
],
},
# modules={"models": ["_models_"]},
generate_schemas=True,
add_exception_handlers=True,
)
Tortoise.init_models(['app.users.models', 'app.contacts.models'], 'models') # <- added
就是这样!
这就像魔咒一样奏效。
这篇关于在Tortoise-ORM+FastAPI中未显示模型关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文