Question

I tried to research but couldn't find a way to handle META requests in Django with Ajax. Refreshing a page everytime kind of destroys the UX. So if the code is something like this:

template

<a href="/like/?id={{ car.id }}" ># of likes: {{ car.likes }}</a>

views.py

def like_page(request):
    if 'id' in request.GET:
        id = request.GET['id']
        car = Cars.objects.get(id=id)
        car.likes += 1
        car.save()
    if 'HTTP_REFERER' in request.META:
        return HttpResponseRedirect(request.META['HTTP_REFERER'])
    return HttpResponseRedirect('/')

So the template sends the id of the object, and in the views it increments the like by 1. everytime this happens. Now the problem is that without Ajax it reloads the page everytime it happens. I am a backend developer, so I have almost no experience with jQuery and Ajax, so I have no clue how to approach this problem.

Any help would be appreciated. Thanks :)

Was it helpful?

Solution

The way to do this is do apply progressive development - make non-js work, and then on top of that make enhancements using ajax or whatever other client technologies you want.

Django request has is_ajax (docs) method which is very useful for progressive development. The idea is that when the request is non-ajax, do whatever you did before, however if it is ajax, return the like counter so that js can update the page:

def like_page(request):
    if 'id' in request.GET:
        id = request.GET['id']
        car = Cars.objects.get(id=id)
        car.likes += 1
        car.save()

    if not request.is_ajax():
        if 'HTTP_REFERER' in request.META:
            return HttpResponseRedirect(request.META['HTTP_REFERER'])
        else:
            return HttpResponseRedirect('/')
    else:
        data = {
            'likes': car.likes
        }
        json_data = json.dumps(data)
        return HttpResponse(json_data, content_type='application/json')

Please note that this returns json data back. This is very useful because it is easily extensible in the future in case you have to return additional information.

Now for the js/jquery stuff:

Template

<a id="car_like" href="/like/?id={{ car.id }}" >
    # of likes: 
    <span id="car_like_count">{{ car.likes }}</a>
</a>

JS

$(document).ready(function () {
    $('#car_like').click(function(event) {
        event.preventDefault();
        var car_like = $(this),
            url = car_like.attr('href');
        $.getJSON(url, function(data) {
            $('#car_like_count', car_like).html(data.likes);
        });
        return false;
    });
});

This will overwrite the default behavior of the like anchor, and will send ajax request. Ajax request will return a new like counter for the car, which js will display in place of the old number. However if for some reason js is not supported, the default action will happen and the like anchor will still work.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top