I have basic web server written in Tornado. Now, I want to add some functionalities that require a database connection. I have chosen MongoDB with Motor library. After following official tutorial relevant part of my main.py
looks something like:
class LoginHandler(BaseHandler):
async def get(self):
db = self.settings['db']
collection = db.test
async def do_find_one():
document = await collection.find_one({"ime" : "stefan"})
pprint.pprint(document)
self.render('login.html')
def main():
parse_command_line()
client = motor.motor_tornado.MotorClient('localhost',27017)
db = client.test
collection = db.test
async def do_find_one():
document = await collection.find_one({"name" : "John"})
pprint.pprint(document)
settings = {
"template_path": os.path.join(os.path.dirname(__file__),"templates"),
"cookie_secret": "random_value_goes_here",
"xsrf_cookies": True,
"login_url": "/login",
"db" : db,
"debug" : True
}
app = tornado.web.Application([
(r'/', WelcomeHandler),
(r'/login', LoginHandler)
],
**settings
)
app.listen(options.port)
tornado.ioloop.IOLoop.current().start()
if __name__ == "__main__":
main()
Following tutorial, it states that I can now run do_find_one
using IOLoop.current().run_sync(do_find_one)
. However, if I do it as such:
tornado.ioloop.IOLoop.current().start()
tornado.ioloop.IOLoop.current().run_sync(do_find_one)
it doesn't change anything, and no adequate result is visible, but if switch lines, like:
tornado.ioloop.IOLoop.current().run_sync(do_find_one)
tornado.ioloop.IOLoop.current().start()
I get the following error:
Traceback (most recent call last):
File "main.py", line 108, in <module>
main()
File "main.py", line 102, in main
tornado.ioloop.IOLoop.current().run_sync(do_find_one)
NameError: name 'do_find_one' is not defined
Should I define do_find_one()
function in main, and then just await
it in get
method of LoginHandler
?
How can I allow server to work, and simultaneously manipulate on database?
Can theese IOLoop
s run on same thread, or I need to create multiple threads (one per IOLoop
or such)?
When the loop has started, you should be able to just await
the async function without having to know which is the current asyncio loop.
async def do_find_one(collection):
document = await collection.find_one({"ime": "stefan"})
pprint.pprint(document)
return 8
class LoginHandler(BaseHandler):
async def get(self):
db = self.settings["db"]
val = await do_find_one(collection=db.test)
print(val)
self.render("login.html")
handlers = [(r"/", WelcomeHandler), (r"/login", LoginHandler)]
def make_app(settings):
return tornado.web.Application(handlers, **settings)
def main():
parse_command_line()
client = motor.motor_tornado.MotorClient("localhost", 27017)
db = client.test
settings = {
"template_path": os.path.join(os.path.dirname(__file__), "templates"),
"cookie_secret": "random_value_goes_here",
"xsrf_cookies": True,
"login_url": "/login",
"db": db,
"debug": True,
}
app = make_app(settings)
app.listen(options.port)
tornado.ioloop.IOLoop.current().start()
if __name__ == "__main__":
main()