kdragger
kdragger

Reputation: 446

Realtime(ish) updates on Web Page using AppEngine

I'm using AppEngine to create a page that I would like to update from the program. Specifically, I am getting some market data and would like to have a table (or something else appropriate) that shows current prices. Let me be clear: I am new to this and think my problem is that I'm not asking the question well enough to find a good (best) answer. I'm not even sure AppEngine is necessarily the way to go. I'll also caveat that I've been learning via Udacity so if code looks familiar -- kudos to Steve Huffman.

I've created the page via jinja2 and I've managed to wrangle the appropriate libraries and sandbox parameters to get market updates. I've created an html table and passed in a dictionary with values for exchanges and bid/ask pairs. The table creates fine -- but when I render again, I get tables repeating down the page rather than one table with updating market prices.

Here is the html/jinja2 (I ditched all the styling to make it shorter):

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Table template</title>
  </head>
  <body>
    <h1>Table template</h1>
    <table>
      {% for exch in mkt_data %}
      <tr>
        <td> <div>{{exch}}</div></td>
        <td> <div>{{mkt_data[exch][0]}}</div></td>
        <td><div>{{mkt_data[exch][1]}}</div></td>
      </tr>
      {% endfor %}
    </table>
  </body>
</html>

Here is the code:

import os
import jinja2
import webapp2
import ccxt

template_dir = os.path.join(os.path.dirname(__file__), 'templates')
jinja_env = jinja2.Environment(loader = jinja2.FileSystemLoader(template_dir),
                                autoescape=True)

class Handler(webapp2.RequestHandler):
    def write(self, *a, **kw):
        self.response.out.write(*a, **kw)

    def render_str(self, template, **params):
        t = jinja_env.get_template(template)
        return t.render(params)

    def render(self, template, **kw):
        self.write(self.render_str(template, **kw))

class MainPage(Handler):
    def get(self):
        self.render("table.html", mkt_data=btc)
        for x in range(3):
            for exch in exchanges:
                orderbook=exch.fetch_order_book('BTC/USD')
                bid = orderbook['bids'][0][0] if len(orderbook['bids'])>0 else None
                ask = orderbook['asks'][0][0] if len(orderbook['asks'])>0 else None
                btc[exch.id]=[bid,ask]
                self.render("table.html", mkt_data=btc)


gdax = ccxt.gdax()
gemini = ccxt.gemini()

exchanges = [gdax, gemini]
btc = {"gemini":[0,1], "gdax":[1,2]}
for exch in exchanges:
    exch.load_markets()

app = webapp2.WSGIApplication([('/', MainPage)], debug=True)

I have 2 questions: First, why am I getting the table repeating? I think I know why, but I want to hear a formal reason. Second, what should I be doing? I originally started learning javascript/node but then it seemed very hard to wrap all the appropriate libraries (was looking into browserify but then thought appengine may be better so I could more easily host something for others to see). I tried integrating some javascript but that did not get me anywhere. Now I've run into Firebase but before I go learn yet another "thing" I wanted to ask how other people do this. I'm certain there are multiple ways but I'm new to web programming; I'm viewing a web page as a nice UI & delivery mechanism.

Some add'l notes: using Ubuntu, virtualenv, ccxt library (for cryptocurrency).

edit: I checked Dan's answer because it offered a solution. I'd love to hear about whether Firebase is "a" more correct solution rather than auto-refreshing.

Upvotes: 0

Views: 75

Answers (1)

Dan Cornilescu
Dan Cornilescu

Reputation: 39809

The repeated table is the result of the multiple self.render() calls inside your MainPage.get() - both above and repetead ones inside the for loop(s).

Update your code to make a single such call, after the for loops building the template values (at the end of MainPage.get())

Upvotes: 2

Related Questions