无法获取模型字段列表

时间:2019-07-26 14:05:50

标签: python mongodb umongo

我需要获取以下模型字段的列表:

@instance.register
class Todo(Document):
    title = fields.StringField(required=True, default='Name')
    description = fields.StringField()
    created_at = fields.DateTimeField()
    created_by = fields.StringField()
    priority = fields.IntegerField()

[
    'title',
    'description',
    'created_at',
    'created_by',
    'priority'
]

所以,我有返回字段列表的函数

def get_class_properties(cls):
    attributes = inspect.getmembers(cls, lambda a: not (inspect.isroutine(a)))
    return [attr for attr in attributes if not (attr[0].startswith('__') and attr[0].endswith('__'))][1]

但是用法给我这个错误 umongo.exceptions.NoDBDefinedError: init must be called to define a db

用法: properties=get_class_properties(Todo)

UPD 这是我的mongo初始化代码:

async def mongo_client(app):
    conf = app["config"]["mongo"]
    client = AsyncIOMotorClient(host=conf["host"], port=conf["port"])
    db = client[conf["db"]]
    instance.init(db)
    await Todo.ensure_indexes()
    app["db_client"]: AsyncIOMotorClient = client
    app["db"] = db
    yield
    await app["db_client"].close()

2 个答案:

答案 0 :(得分:0)

这是this answer作者的this library的副本/粘贴:

  

据我所知,当您尝试使用时会引发此异常   懒客户端,而没有正确初始化它们。任何懒惰的   uMongo希望在使用数据库之前指定使用的数据库。   用法。您所需要做的就是指定使用的数据库,并   调用您的惰性实例的init方法,如下所示:

from motor.motor_asyncio import AsyncIOMotorClient
from umongo import MotorAsyncIOInstance

client = AsyncIOMotorClient("mongodb://user:password@host:port/")
client = client["test_database"]
lazy_umongo = MotorAsyncIOInstance()
lazy_umongo.init(client)
     

作为示例,您可以查看Auth/Auth microservice代码,其中   定义的文档和与实际存储在不同的文件中   用法。另外,这些文件以代码为例(documents.py和   prepare_mongodb.py)将帮助您找到解决方案。

答案 1 :(得分:0)

诀窍是

properties=get_class_properties(Todo)

早于

调用

async def mongo_client(app):

解决方案是按正确的顺序使用事物(请参阅代码注释)

async def init_app(argv=None):
    app = web.Application(middlewares=[deserializer_middleware], logger=logger)
    app["config"] = config

    conf = app["config"]["mongo"]
    client = AsyncIOMotorClient(host=conf["host"], port=conf["port"])
    db = client[conf["db"]]
    instance.init(db)
    # Remove this line:
    # app.cleanup_ctx.append(mongo_client)
    app.cleanup_ctx.append(api_client)

    register_routes(app)
    return app
def register_routes(app: web.Application):
    # Use here:
    todo_resource = RestResource(
        entity='todo',
        factory=Todo,
        properties=get_class_properties(Todo)
    )
    todo_resource.register(app.router)