2

I am deploying a website using Django. There is an application called 'forum', supporting a discussion forum on my website.

The url of the discussion forum is 'XXX.com/forum/roomY'. I want to refresh a div id = ''chat'', which includes a message list, on this page when users click a refresh button. I want to use AJAX to do that.

But I find that I could not call the function updatestatementlist(request) to retrieve the updated message list so it can be passed to the on this page.

/forum/views.py def updatestatementlist(request):

log.debug("call statementlist function")
statements = Statement.objects.filter(discussion=discussion)
return render(request, 'forum/statementlist.html', {
    'statements': statements
    })

I cannot see the log info so I think by clicking the button I fail to call this function.

The main html page of the discussion forum is /forum/discussion.html, which is under the template folder. I extract the html code within the div id = "chat" to a separate html /forum/statementlist.html as suggested here and several other SO posts.

/forum/discussion.html

<button id = "Refresh"> Refresh </button>
<div id="chat">
{% include 'forum/statementlist.html' %}
</div>

/forum/statementlist.html

{% load mptt_tags %}
{% recursetree statements %}
    // display each statement
{% endrecursetree %}

forum.js

//When users click the refresh button
    $("#Refresh").on("click", function(event){
    alert("Refresh clicked")
    $.ajax({
        url: '',
        type: "GET",
        success: function(data) {
            alert("success")
            var html = $(data).filter('#chat').html();
            $('#chat').html(html);
        }
    });
});

I also tried a few other url in this AJAX request: {% url updatestatementlist %}, {% url 'updatestatementlist' %}. But then I think it should be set to empty because I don't want to be redirected to another url. The discussion forum has a url of 'XXX.com/forum/roomY', by clicking the refresh button on this page I only want to refresh the div and fetch an updated statement list from the server.

BTW, I can see the two alerts after I click the button.

/forum/urls.py

urlpatterns = [
...
url(r'^(?P<label>[\w-]{,50})/$', views.discussion_forum, name='discussion_forum'),
url(r'^(?P<label>[\w-]{,50})/$', views.statementlist, name='statementlist'),

]

/forum/views.py def discussion_forum() is used to load all the information when the user first arrives at this forum.

I guess my problem might be that 1) the AJAX is wrong; 2) the url is wrong so that the updatestatementlist() can not be called.

Can anyone help me with that? Thanks a lot! Let me know if you need any other information!

Packages related:

Django==1.9.3

django-mptt==0.8.7

Affozhizhi
  • 21
  • 4

1 Answers1

0

On the client side, Set your request header to X-Requested-With to XMLHttpRequest, Django use this specific header to determine whether it is a Ajax Request:

Here is the a snippet from Django source code: https://docs.djangoproject.com/en/2.2/_modules/django/http/request/#HttpRequest.is_ajax

def is_ajax(self):
    return self.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'

After defining this header, you need to add one logic layer into your view function.

def your_view_func(request, *args, **kwargs):
    if request.is_ajax():
        ...
        return render(request, <your_ajax_template>)
    return render(request, <your_normal_template>)

Updated:

I prefer the raw XMLHttpRequest API, if you use Jquery, add the berforeSend property.

$.ajax({
  type: "GET",
  beforeSend: function(request) {
    request.setRequestHeader("X-Requested-With", "XMLHttpRequest");
  },
  ...
});

Why X-Requested-With but not HTTP_X_REQUESTED_WITH?

HTTP headers in the request are converted to META keys by converting all characters to uppercase, replacing any hyphens with underscores and adding an HTTP_ prefix to the name.

https://docs.djangoproject.com/en/2.2/ref/request-response/#django.http.HttpRequest.META

minglyu
  • 2,958
  • 2
  • 13
  • 32
  • can you be more specific about how do I write the ajax? thanks. I am new to javascript. – Affozhizhi Aug 18 '19 at 14:45
  • Thanks. I add the beforeSend property but I still think by pressing the refresh button I fail to send the ajax request to views.py/updatestatementlist(). Because within updatestatementlist I have two branches: if or else request.is_ajax(). No log info from both branches are displayed. Might it be my url pattern is wrong? – Affozhizhi Aug 18 '19 at 15:52
  • I won't use a ``include`` tag for AJAX request, it loads only once on the page loading, try to fetch the JSON data back using Django ``JsonResponse``, and then dynamically add html data by registering an ``onclick`` event to your element. – minglyu Aug 18 '19 at 16:40