0

我目前正在开发个人理财 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 以等待其结果?谢谢您的帮助 !

4

0 回答 0