简体   繁体   中英

Passing Django template variables into javascript in GAE

I'm trying to create a wordcloud with the Google's visualization sample:

<link rel="stylesheet" type="text/css" href="http://visapi-gadgets.googlecode.com/svn/trunk/wordcloud/wc.css"/>
<script type="text/javascript" src="http://visapi-gadgets.googlecode.com/svn/trunk/wordcloud/wc.js"></script>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>


<div id="wcdiv"></div>
<script type="text/javascript">
  google.load("visualization", "1");
  google.setOnLoadCallback(draw);
  function draw() {
    var data = new google.visualization.DataTable();
    data.addColumn('string', 'Text1');
    data.addRows(160);
 {{datamade}}
    var outputDiv = document.getElementById('wcdiv');
    var wc = new WordCloud(outputDiv);
    wc.draw(data, null);
  }
</script>

I'm creating {{datamade}} in my main.py file, then passing it as a template variable:

   tweets1 = []

    fetched = urlfetch.fetch("http://api.twitter.com/1/statuses/user_timeline.json?screen_name="+tweets.username+"&count=200")
    statustext = json.loads(fetched.content)

    for tweetInfo in statustext:
     tweets1.append(tweetInfo["text"])

    datamake = []

    n = 1
    for n in range(160):
   tweet = tweets1[n]
   datamake.append("data.setCell("+str(n)+", 0, '"+tweet+"');")

    datamade = '<br>'.join(datamake)


    content_values = {
        'datamade':datamade,
        'username':tweets.username,
        }

When I print the {{datamade}}, I see the correct Javascript code. And when I hardcode the values into my statuspage.html, the javascript executes correctly. But when I pass the variable directly into the javascript, the javascript does not execute properly.

It my javascript executing prior to the template value is passed? Not sure how to adjust for this. I'd appreciate any advice.

Disclaimer: I'm a total newb.

Thank you! Jake

I would suggest making a number of changes to your code. Instead of generating javascript calls (data.setCell), generate the table and let Google's DataTable process it.

import os
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext.webapp import template
from google.appengine.api import urlfetch

class GetTweetsHandler(webapp.RequestHandler):
    def get(self):
        user = self.request.get('user', 'someuser')
        fetched = urlfetch.fetch("http://api.twitter.com/1/statuses/user_timeline.json"
                                 "?screen_name=" + user + "&count=200")
        tweets = json.loads(fetched.content)

        data = {'cols': [{'type': 'string', 'label': 'Tweets'}],
                'rows': [{'c': [{'v': tweet["text"]}]} for tweet in tweets]}

        template_values = {'tweet_data': json.dumps(data),
                           'user': user}
        path = os.path.join(os.path.dirname(__file__), 'index.html')
        self.response.out.write(template.render(path, template_values))


 def main():
   application = webapp.WSGIApplication([('/gettweets', GetTweetsHandler)],
                                        debug=True)
   run_wsgi_app(application)

 if __name__ == '__main__':
   main()

So then you will just need to pass the datatable you generated to Google's DataTable. Luckily that is a very small change to your template:

<html>
<head>
    <link rel="stylesheet" type="text/css" href="http://visapi-gadgets.googlecode.com/svn/trunk/wordcloud/wc.css"/>
    <script type="text/javascript" src="http://visapi-gadgets.googlecode.com/svn/trunk/wordcloud/wc.js"></script>
    <script type="text/javascript" src="http://www.google.com/jsapi"></script>
    <script type="text/javascript">
      google.load("visualization", "1");
      google.setOnLoadCallback(draw);
      function draw() {
        var tweet_data = {{tweet_data}};
        var data = new google.visualization.DataTable(tweet_data);
        var outputDiv = document.getElementById('wcdiv');
        var wc = new WordCloud(outputDiv);
        wc.draw(data, null);
      }
    </script>
</head>
<body>
    <div id="wcdiv"></div>
    <form method='get'>
       <input type='text' name='user' value="{{user}}"></input>
       <input type='submit'></input>
    </form>
</body>
</html>

Call it by going to http://localhost:8080/gettweets/someuser

Jake, offhand it looks like you're putting '<br>' tags into your js code. 'datamade' could be:

data.setCell('foo', 0, 'bar');<br>data.setCell('foo', 0, 'bar');

This is not executable js because html tags aren't read by a js interpreter. You'd effectively be writing an incomplete comparison expression (nothing is less than a variable called br). Don't bother trying to insert the page breaks into your code, and just join on an empty string. datamade = ''.join(datamake)

Edit: In general though, it's not good practice to use a loop to print out 100+ lines of js. You're better off sending the whole object to js in json format and looping over it afterward in the client.

I'd advise this:

<link rel="stylesheet" type="text/css" href="http://visapi-gadgets.googlecode.com/svn/trunk/wordcloud/wc.css"/>
<script type="text/javascript" src="http://visapi-gadgets.googlecode.com/svn/trunk/wordcloud/wc.js"></script>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>


<div id="wcdiv"></div>
<script type="text/javascript">
  google.load("visualization", "1");
  google.setOnLoadCallback(draw);
  function draw() {
    var data = new google.visualization.DataTable();
    data.addColumn('string', 'Text1');
    data.addRows(160);
    var tweets = {{tweets}};

    for (var i in tweets) {
       data.setCell(i, 0, tweets[i]);
    }

    var outputDiv = document.getElementById('wcdiv');
    var wc = new WordCloud(outputDiv);
    wc.draw(data, null);
  }
</script>

And have you server file show the following:

tweets1 = []

fetched = urlfetch.fetch("http://api.twitter.com/1/statuses/user_timeline.json?screen_name="+tweets.username+"&count=200")
statustext = json.loads(fetched.content)

for tweetInfo in statustext:
 tweets1.append(tweetInfo["text"])

tweetsJson = json.dumps(tweets1)

content_values = {
    'tweets':tweetsJson,
    'username':tweets.username,
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM