我目前正在开发个人理财 api,并且正在努力返回一些在 pydantic 模型中异步的功能。我正在使用 FastApi、pydantic 和 Tortoise ORM。基本上,目标是返回给定用户的所有 Budget.amount (month_base) 的总和,但问题是这个函数是异步的,当我将它作为计算字段传递给 PydanticMeta 类时,它不会被等待,因此返回值不是正确的类型,如以下错误中所述:
错误:hypercorn.error:ASGI 框架中的错误 [...] 文件“pydantic/main.py”,第 573 行,在 pydantic.main.BaseModel.from_orm pydantic.error_wrappers.ValidationError:用户month_base 值的1 个验证错误不是一个有效的浮点数(type=type_error.float)
/home/jon/ml-v3/venv/lib/python3.8/site-packages/tortoise/contrib/pydantic/base.py:88:RuntimeWarning:从未等待协程'User.month_base'
我在models.py中的代码:
class SoftDeleteMixin:
deleted = fields.BooleanField(default=False)
deletion_date = fields.DatetimeField(null=True)
def soft_delete(self):
"""
Annotate the object as deleted and saves the deletion_date
---Return---
False if the object is already deleted else True
"""
if self.deleted:
return False
self.deleted = True
self.deletion_date = datetime.today()
return True
@classmethod
async def get_non_deleted(cls, user_id: int):
return await cls.filter(Q(user_id=user_id) & Q(deleted=False))
class User(Model):
id = fields.IntField(pk=True)
gender = fields.IntEnumField(Gender, default=Gender.not_specified)
configured = fields.BooleanField(default=False)
start_date = fields.DatetimeField(null=True)
email = fields.CharField(max_length=100, unique=True, index=True)
full_name = fields.CharField(max_length=50)
password_hash = fields.CharField(max_length=128, null=True)
confirmed = fields.BooleanField(default=False)
general_terms_and_conditions_of_sale_signed = fields.BooleanField(default=False)
privacy_policy_signed = fields.BooleanField(default=False)
signature_date = fields.DatetimeField(null=True)
# One-To-Many relationships
budgets: fields.ReverseRelation['Budget']
origins: fields.ReverseRelation['Origin']
long_budgets: fields.ReverseRelation['LongBudget']
stocks: fields.ReverseRelation['Stock']
outcomes: fields.ReverseRelation['Outcome']
incomes: fields.ReverseRelation['Income']
costs: fields.ReverseRelation['Cost']
transfer: fields.ReverseRelation['Transfer']
images: fields.ReverseRelation['Image']
async def get_budgets(self):
return await Budget.get_non_deleted(user_id=self.id).order_by('order')
async def month_base(self) -> float:
return sum(map(lambda budget: budget.month_budget,
await self.get_budgets()))
class PydanticMeta:
computed = ['month_base', ]
exclude = ['password_hash',
'general_terms_and_conditions_of_sale_signed',
'privacy_policy_signed',
'signature_date',
'confirmed']
我在 schemas.py 中的代码:
User = pydantic_model_creator(models.User, name='User')
UserIn = pydantic_model_creator(models.User,
exclude=('configured',
'start_date'),
name='UserIn',
exclude_readonly=True)
我在 main.py 中的代码:
async def get_current_user(token: str = Depends(oauth2_schema)):
try:
payload = jwt.decode(token, JWT_SECRET, algorithms=['HS256'])
user = await User.get(id=payload.get('id'))
except:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail='Invalid username or password'
)
return await sch.User.from_tortoise_orm(user)
@app.get('/user', response_model=sch.User)
async def read_user(user: sch.User = Depends(get_current_user)):
return user
我应该如何继续将我的 month_budget 字段传递给我的用户模式,但指定给 pydanticModel 以等待其结果?谢谢您的帮助 !