Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rendering JSON objects using a Django template after an Ajax call

I've been trying to understand what's the optimal way to do Ajax in Django. By reading stuff here and there I gathered that the common process is:

  1. formulate your Ajax call using some JavaScript library (e.g., jQuery), set up a URL pattern in Django that catches the call and passes it to a view function

  2. in the Python view function retrieve the objects you are interested in and send them back to the client in JSON format or similar (by using the built in serializer module, or simplejson)

  3. define a callback function in JavaScript that receives the JSON data and parses them, so to create whatever HTML is needed to be displayed. Finally, the JavaScript script puts the HTML wherever it should stay.

Now, what I still don't get is how are Django templates related to all of this? Apparently, we're not making use of the power of templates at all. Ideally, I thought it'd be nice to pass back a JSON object and a template name, so that the data could be iterated over and an HTML block is created. But maybe I'm totally wrong here...

The only resource I found that goes in this direction is this snippet (769) but I haven't tried it yet. Obviously, what's going to happen in this case is that all the resulting HTML is created on the server side, then passed to the client. The JavaScript-callback function only has to display it in the right place.

Does this cause performance problems? If not, even without using the snippet above, why not formatting the HTML directly in the backend using Python instead of the front-end?

Many thanks!

UPDATE: please use snippet 942 because it is an enhanced version of the one above! I found that the inheritance support works much better this way..

like image 545
magicrebirth Avatar asked May 19 '09 11:05

magicrebirth


3 Answers

Hey thanks vikingosegundo!

I like using decorators too :-). But in the meanwhile I've been following the approach suggested by the snippet I was mentioning above. Only thing, use instead the snippet n. 942 cause it's an improved version of the original one. Here's how it works:

Imagine you have a template (e.g., 'subtemplate.html') of whatever size that contains a useful block you can reuse:

     ........
    <div id="results">          
        {% block results %}
            {% for el in items %}
                   <li>{{el|capfirst}}</li>
            {% endfor %}
        {% endblock %}      
    </div><br />
     ........

By importing in your view file the snippet above you can easily reference to any block in your templates. A cool feature is that the inheritance relations among templates are taken into consideration, so if you reference to a block that includes another block and so on, everything should work just fine. So, the ajax-view looks like this:

from django.template import loader
# downloaded from djangosnippets.com[942]
from my_project.snippets.template import render_block_to_string

def ajax_view(request):
    # some random context
    context = Context({'items': range(100)})
    # passing the template_name + block_name + context
    return_str = render_block_to_string('standard/subtemplate.html', 'results', context)
    return HttpResponse(return_str)
like image 143
magicrebirth Avatar answered Nov 16 '22 13:11

magicrebirth


Here is how I use the same template for traditional rendering and Ajax-response rendering.

Template:

<div  id="sortable">

{% include "admin/app/model/subtemplate.html" %}
</div>

Included template (aka: subtemplate):

<div id="results_listing">
{% if results %}
    {% for c in results %}
        .....
    {% endfor %}
{% else %}

The Ajax-view:

@login_required
@render_to('admin/app/model/subtemplate.html')#annoying-decorator
def ajax_view(request):
    .....

    return { 
        "results":Model.objects.all(),
    }      

Of course you can use render_to_response. But I like those annoying decorators :D

like image 13
vikingosegundo Avatar answered Nov 16 '22 14:11

vikingosegundo


There's no reason you can't return a rendered bit of HTML using Ajax, and insert that into the existing page at the point you want. Obviously you can use Django's templates to render this HTML, if you want.

like image 7
Daniel Roseman Avatar answered Nov 16 '22 14:11

Daniel Roseman