2

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

1
  • Try using 'datamade': SafeString(datamade) instead of 'datamade': database. Django could be escaping your javascript/html, something that using a SafeString would prevent. Commented Nov 14, 2010 at 21:29

2 Answers 2

1

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

Sign up to request clarification or add additional context in comments.

11 Comments

By the way, you can find the syntax for datatable object literal notation here: code.google.com/apis/visualization/documentation/… Check out the example.
Thanks very much! For some reason, getting the following error:main.py", line 54, in GetTweetsHandler template_values = {'tweet_data': json.dumps(data)} NameError: name 'data' is not defined
Did you make sure you copied the line right above that? It should be a working example, I did test it.
Woot! it worked, thanks so much. I'll send you the final version when it's ready.
Quick follow-up: how do I pass input from a form into the Action:URL? In other words, if gettweets/someuser calls the GetTweetsHandler method, how do I call it from a user's input into a form?
|
0

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,
    }

2 Comments

Thanks dude, still not working for some reason. Also, the code calls for a variable, not a string: visapi-gadgets.googlecode.com/svn/trunk/wordcloud/doc.html
Yeah, I see that. You were right about that last part. I would definitely check the javascript code that is being spit out by python. View source on your page to see it and check for syntax errors.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.