无法获取模型字段列表

Can't get list of model fields

我需要获取模型字段列表,例如:

@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'
]

所以,我有 returns 字段列表

的功能
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()

这是 this answer from the author of this library 的 copy/paste:

As far as I remeber, this exception raises when you're trying to use lazy clients without initializing them properly. Any lazy class of uMongo expects that the used database will be specified before the usage. Everything that you need is to specify the used database and invoke the init method of your lazy instance, like this:

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)

As an example you can look into Auth/Auth microservice code, where documents defined and store in the separate files from the actual usage. Also these files with code as examples (documents.py and prepare_mongodb.py) will help you to find a solution.

诀窍在于

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)