Search code examples
javascriptdjangoajaxxmlhttprequest

Ajax xhr onload not being called within django app


I have a Django app with user posts. I am trying to add a 'like' / voting system. I had done this through complete page refreshes through a redirect where the vote was made then redirected back to the same page with the new vote / like total updates. I then was reading about ajax and how I could update part of a page without a full reload.

let up_vote = document.getElementById("up-vote").addEventListener('click', () => {
    console.log("clicked");
    let xhr = new XMLHttpRequest();
    xhr.open('GET', "{% url 'up-vote' %}", true);
    console.log(xhr);
    xhr.onload = () => {
        console.log("inside");

    };
    console.log("outside");
});

So far my js looks like this. When I click on "up-vote", "clicked" is printed along with the xhr object. However, onload appears to never be called as "inside" is never printed but instead passes straight over to "outside".

I have a feeling that the issue is to do with the URL path but I don't know how to get path properly. The basic file structure of this app is:

app
|-static/app  
    |-scripts/*this js file*/  
    |-images  
    |-styles  
|-templates/app  
    |-html files
|-views.py *where the request is being made*
|-urls.py

urls.py contains,

urlpatterns = [
    ...
    path('post/<int:pk>/up/', up_vote, name='up-vote'),
    ...
]

and the views.py contain,

@login_required()
def up_vote(request, pk):
    print("HI")
    obj = get_object_or_404(Post, pk=pk)
    uid = request.user.id
    if not obj.votes.exists(uid):
        obj.votes.up(uid)
    data = {
        'votes': obj.votes.count()
    }
    return JsonResponse(data)

Any help or advice greatly appreciated :)

p.s. I have also tried xhr.onreadystate which is what gives to the thought of the URL path being wrong.


Solution

  • AJAX request (as you might have guessed from its name), is asynchronous, so it will really pass straight to 'outside'.

    In addition to that, you have to call xhr.send()

    let up_vote = document.getElementById("up-vote").addEventListener('click', () => {
        console.log("clicked");
        let xhr = new XMLHttpRequest();
        xhr.open('GET', "{% url 'up-vote' %}", true);
        console.log(xhr);
        xhr.onload = () => {
            console.log("inside");
        };
        xhr.send()
        console.log("outside");
    });
    

    PS: I think your URL/views have issues. Your view and routes requires a pk, but your {% url 'up-vote' %} doesn't pass a pk to it