1

I have a page that loads a lot of analytics & data on specific pages and so far its loading okay but I'm wondering if I can speed it up. The idea I had to try to speed it up was to render each part of the separately.

For example, look at your profile page on SO: it has Questions, Answers, Reputation, Tags, Accounts, Badges, Votes cast, which in my current model would be gathered in the view.py and then rendered by the template. But what if the "Reputation" or "tags" query is slow because of XYZ reason, it will slow down the entire page load even if its not super important for most users. I thought about solving this using JavaScript to make a request and render the json reply on the page asynchronously but I really like Pyramid and using Python, so if possible I would like to use tools I already know than learn javascript to do this. The benefit of this approach is I can load/display the top of the page first and render the rest of the page as the queries complete or order the rending by speed of queries.

Is this possible, or do you have any suggestions on how to do this?

tshepang
  • 12,111
  • 21
  • 91
  • 136
Lostsoul
  • 25,013
  • 48
  • 144
  • 239
  • I suggest you to add "javascript" and "jquery" tags to the question to attract more people with relevant knowledge. I don't have enough rep to do this myself. – Sergey Jul 19 '12 at 21:42
  • @Sergey I know I can def. do this with javascript but I was trying to test my luck and see if there was something I can do using only python(and avoiding having to learn a new language if its not needed). – Lostsoul Jul 19 '12 at 21:50

1 Answers1

2

This surely is possible but the implementation is almost completely has nothing to do with Pyramid or Jinja2. The way Pyramid (or any other web framework) works is that it gets a bit of text from the client (which is abstracted into the request object) and basically returns another blob of text in response, so the operation is more or less atomic - the response is not sent back to the client until the template engine finished generating the full text of the page.

Actually, there is a way to make Pyramid to send data to the client bit after bit, which will make the browser render the page incrementally (like back at the time of dial-up connections) - which is writing directly into the file-like object which represent response's body:

import time
def some_view(request):
    for i in range(1, 31):
        request.response.body_file.write(".")
        time.sleep(1)

but this approach is a bit limited because you can only append data to what you've already sent, there's no way to, say, display a "please wait, the chart is loading" message and replace it with the real chart, or even to load page header and footer first and then insert something in the middle. Also, this approach would require you to render the template manually or not to use templates at all. I only used this for some long-running batch operations

As you mentioned in the question, a better technique involves loading bits of the page from separate URLs with JavaScript. I believe the blocks loaded asynchronously are often called "partials".

  • you register a few separate views which represent your main page and the bits you want to insert, so, say, /questions/123454 would load the main part of the page, /questions/123454/badges would load the block with badges and /questions/123454/related would load the list of related questions

  • you define placeholders in your page where the partials will be inserted:

    < div id="badges-partial" >Loading...< /div >

  • you add a small bit of javascript to your page to load the partials (well, it will be small if you use jquery :) :

    $(function () {
        $("#badges-partial").load("/questions/123454/badges");
        $("#related-partial").load("/questions/123454/related");
    });
    

so, as you can see, the JavaScript solution is cleaner, easier and more flexible.

Sergey
  • 11,892
  • 2
  • 41
  • 52
  • okay, I'll go down the jquery route..I have another question, maybe slightly unrelated..Is there a way in pyramid to ensure that only my apps are getting json responses? I'm not ready to open a api to the world yet but in my source code you can see the pyramid url's I'm querying. – Lostsoul Jul 19 '12 at 21:52
  • 1
    @Lostsoul: There's no difference between having your HTML publicly accessible and the views that return JSON data being publicly accessible. If you need to restrict access you need to implement authentication in your app - Pyramid has extensive docs on this. I mean, in World Wide Web *every page* is a read-only API method and every form is a read-write method - they just happen to use HTML as data format. JSON API is not different from that. – Sergey Jul 20 '12 at 03:00
  • Thanks true and a good way of thinking about it. I'll look at security a bit more, I guess I'm trying to prevent random people from accessing my sites api without any controls(and slowing my server down for people accessing the site). – Lostsoul Jul 20 '12 at 07:47