I need to get list of model fields like:
@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()
to
[
'title',
'description',
'created_at',
'created_by',
'priority'
]
So, I have function that returns list of fields
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]
But usage gives me this error
umongo.exceptions.NoDBDefinedError: init must be called to define a db
Usage:
properties=get_class_properties(Todo)
UPD Here is my mongo initialization code:
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()
The trick was that
properties=get_class_properties(Todo)
invokes earlier than
async def mongo_client(app):
Solution is use things in right order (see comments to code)
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)