0

I have a simple chat application in Tornado powered with RethinkDB.

Am trying to integrate this tornado chat application to run with django site.

For that reason, I have adopted below in rechat.py in order for it to work with django.

  1. Namespaces tornado.wsgi and django.core.wsgi (get_wsgi_application)
  2. Set environment variable for Django settings.py os.environ['DJANGO_SETTINGS_MODULE'] = 'djangoapp.settings'

When I try to run it after the above changes, it connects the db server, but doesn't do anything. What am I missing? How can I make this tornado app to work with django 1.8 site?

Below is my code of rechat.py (https://github.com/v3ss0n/rechat) -

import logging
import tornado.escape
from tornado.ioloop import IOLoop
import tornado.web
import os.path
import rethinkdb as r
from tornado import httpserver
from time import time
# from tornado.concurrent import Future
from tornado import gen
from tornado.options import define, options, parse_command_line
import tornado.wsgi
from django.core.wsgi import get_wsgi_application

define("port", default=8888, help="run on the given port", type=int)
define("debug", default=True, help="run in debug mode")

def setup_db(db_name="rechat", tables=['events']):
    connection = r.connect(host="localhost")
    try:
        r.db_create(db_name).run(connection)
        for tbl in tables:
            r.db(db_name).table_create(tbl, durability="hard").run(connection)
        logging.info('Database setup completed.')
    except r.RqlRuntimeError:
        logging.warn('Database/Table already exists.')
    finally:
        connection.close()

class RechatApp(tornado.web.Application):
    def __init__(self, db):
        handlers = [
            (r"/", MainHandler),
            (r"/a/message/new", MessageNewHandler),
            (r"/a/message/updates", MessageUpdatesHandler),
        ]
        settings = dict(cookie_secret="_asdfasdaasdfasfas",
                        template_path=os.path.join(
                            os.path.dirname(__file__), "templates"),
                        static_path=os.path.join(
                            os.path.dirname(__file__), "static"),
                        xsrf_cookies=True,
                        debug=options.debug)
        self.db = db
        logging.info(db)
        tornado.web.Application.__init__(self, handlers, **settings)


class BaseHandler(tornado.web.RequestHandler):
    def initialize(self):
        self.db = self.application.db
        self.evt = r.table("events")

class MainHandler(BaseHandler):
    @gen.coroutine
    def get(self):
        curs = yield self.evt.run(self.db)
        messages = []
        while (yield curs.fetch_next()):
            item = yield curs.next()
            messages.append(item)

        self.render("index.html", messages=messages)


class MessageNewHandler(BaseHandler):
    @gen.coroutine
    def post(self):
        message = {
            "body": self.get_argument("body")
        }
        # to_basestring is necessary for Python 3's json encoder,
        # which doesn't accept byte strings.
        start = time()
        messages = (yield self.evt.insert(message).run(self.db))
        time_taken = time() - start
        logging.warn("DBINSERT: %s seconds" % time_taken)
        message['id'] = messages['generated_keys'][0]
        message["html"] = tornado.escape.to_basestring(
            self.render_string("message.html", message=message))
        if self.get_argument("next", None):
            self.redirect(self.get_argument("next"))
        else:
            self.write(message)


class MessageUpdatesHandler(BaseHandler):
    @gen.coroutine
    def post(self):
        curs = yield self.evt.changes().run(self.db)

        while (yield curs.fetch_next()):
            feed = yield curs.next()
            message = {
                'id': feed['new_val']['id'],
                'html': tornado.escape.to_basestring(
                    self.render_string("message.html",
                                       message=feed['new_val']))}
            break
        self.finish(dict(messages=[message]))

@gen.coroutine
def main():
    """ Async main method. It needed to be async due to r.connect is async . """
    parse_command_line()
    os.environ['DJANGO_SETTINGS_MODULE'] = 'djangoapp.settings'
    db_name = "rechat"
    setup_db(db_name)
    r.set_loop_type("tornado")
    db = yield r.connect("localhost", db=db_name)
    #Single db connection for everything thanks a lot Ben and Jeese
    http_server = httpserver.HTTPServer(RechatApp(db))
    http_server.listen(options.port)

if __name__ == "__main__":
    IOLoop.current().run_sync(main)
    IOLoop.current().start()
Sathish
  • 133
  • 7
  • You've wrote about adoption of wsgi... anything else but import is done or I am missing something? have you tried to use curl to navigate to GET / or POST /a/message/new? – kwarunek Dec 23 '15 at 21:32
  • Hi @kwarunek, you are right, I removed couple of statements with wsgi.. I tried adding wsgi as per some example of Python 2.7, but it doesn't work in 3.4. Could you please suggest how to use wsgi and container in main() ? – Sathish Dec 23 '15 at 21:38
  • As stated in http://www.tornadoweb.org/en/stable/_modules/tornado/wsgi.html "In WSGI mode asynchronous methods are not supported" – kwarunek Dec 24 '15 at 11:22
  • Hi @kwarunek, I have somehow implemented the chat feature, but am not sure how to enable private messaging.. Could you please look into http://stackoverflow.com/questions/34461046/private-messaging-using-sockjs-tornado ? – Sathish Dec 25 '15 at 12:30

0 Answers0