0

I have a django project that I'm trying to add a custom "online" state to (boolean field in a model). I want to refresh a div periodically to show if a user is now online. The div which is refreshed, with the class button-refresh, is in an included HTML file.

The issue is that the include doesn't work with my for loop in the original HTML file, none of the "professionals" data is retrieved from the server. I'm pretty new to django, my assumption is that the refresh_professionals.html file is retrieved with the ajax request and is entirely separate from the all_professionals.html and then included, without ever being a part of the for loop meaning that the {{ professional.professional_profile.online }} syntax doesn't work.

Any ideas on how to fix this issue? If there is a better way to do this, let me know. Thanks.

all_professionals.html

{% for professional in professionals %}
...
   {{ professional.name }}
   {% include 'professionals/refresh_professionals.html' %}
...
{% endfor %}
...
{% block postloadjs %}
    {{ block.super }}
    <script>var global_url = "{% url 'refresh_professionals' %}";</script>
    <script src="{% static 'professionals/js/professionals.js' %}"></script>
{% endblock %}

refresh_professionals.html

<div class="col button-refresh">
    {% if professional.professional_profile.online is True %}
        <p class="custom-button mb-1 w-25 mx-auto">Chat</p>
    {% else %}
        <p class="custom-button-disabled mb-1 w-25 mx-auto">Unavailable</p>
    {% endif %}
    <p>{{ professional.price_chat }}/min</p>    
</div>

professionals.js

$(document).ready(function(){
    setInterval(function() {
        $.ajax({
            url: global_url,
            type: 'GET',
            success: function(data) {
                $('.button-refresh').html(data);
            }
        });
    }, 5000)
});

urls.py

urlpatterns = [
    path('', views.view_all_professionals, name='view_all_professionals'),
    path('refresh/', views.refresh_professionals, name='refresh_professionals'),
]

views.py

def view_all_professionals(request):
    """A view to return the professionals page"""
    professionals = Professional.objects.all()
    languages = Languages.objects.all()

    context = {
        'professionals': professionals,
        'languages': languages,
    }
    return render(request, 'professionals/all_professionals.html', context)


def refresh_professionals(request):
    """A view to refresh the online button section"""
    professionals = Professional.objects.all()

    context = {
        'professionals': professionals,
    }
    return render(request, 'professionals/refresh_professionals.html', context)

EDIT

I've followed Daniel's advice and am now returning a JSON object. This is the updated code

professionals.js

$(document).ready(function(){
    setInterval(function() {
        $.ajax({
            url: global_url,
            type: 'GET',
            success: update_professionals, 
        });
    }, 5000)
});

function update_professionals(response){
    // unpack the response (context) from our view function:
    var professionals = response.professionals; 
    // update html:
    var i;
    for (i = 0; i < professionals.length; i++) {
        $('#professional-name' + i).text('professionals.name' + i);
    };
};

views.py

def refresh_professionals(request):
    """A view to refresh the professionals section page"""

    professionals = Professional.objects.all()
    professionals = serializers.serialize("json", professionals)
    context = json.dumps({
        'professionals': professionals,
    })

    return HttpResponse(context)

The issue I'm facing now is referencing the professionals data. It's returning uncaught errors. The forloop is necessary because in my HTML I've got a series of IDs with a number attached to the end using a django forloop.counter. Any advice would be appreciated. Thanks.

4
  • You're almost there - instead of trying to render a template with the refresh_professionals method you should return a json object of the data. Then, in js, you can update the html elements with the data returned from the refresh_professionals ajax call. Commented Oct 3, 2020 at 15:13
  • @Daniel I'm not entirely sure what you mean by modifying my JS, I'm quite inexperienced with Ajax. I've changed my view to look like this ``` def refresh_professionals(request): professionals = Professional.objects.all().values() professionals_list = list(professionals) return JsonResponse(professionals_list, safe=False) ``` but am unsure how to modify the JS I provided above. Commented Oct 3, 2020 at 16:08
  • See my answer below. I'm happy to elaborate on any unclear points. Commented Oct 3, 2020 at 16:21
  • Hi,you are returning json from backend you need to parse it using $.parseJSON(response); or give dataType: 'json' to your ajax. Commented Oct 4, 2020 at 12:23

1 Answer 1

1

Okay, lets assume we have a view function like so:

from django.http import HttpResponse
import json

def refresh_professionals(request):

    """A view to refresh the online button section"""

    professionals = Professional.objects.all()

    # convert to json friendly format:
    professionals = ... 

    context = json.dumps({
        'professionals': professionals,
    })

    return HttpResponse(context)

This assumes professionals now looks something like (the actual structure will obviously be different):

professionals = {"id":1, "name":"Jason"}

Now, in our js file we should have an ajax request like so (wrapped in a setInterval method, etc.):

$.ajax({
    url: global_url,
    type: 'GET',
    success: update_professionals, // reference to an ajax-success function
 });

And our success function like so:

update_professionals(response) {
    
    // unpack the response (context) from our view function:
    // use JSON.parse() to convert a string to json
    var professionals = JSON.parse(response.professionals); 

    // update html:
    $('#professional-name').text(professionals.name)
}

This assumes we have an HTML element like so:

<div id="professionals-name"> Sue </div>

The difference is we are using js to update the HTML on the fly instead of trying to re-render an HTML template likely will require a page refresh.

Sign up to request clarification or add additional context in comments.

5 Comments

Great advice, I'm much further along than I was before. I'm getting a JSON response as expected, but I'm not managing to correctly replace the HTML. I'm getting an uncaught TypeError, it can't read ....text(professionals.name); Any ideas? I'll update my original post with my current code.
Can you share your professionals json? You can do console.log(response.professionals) in js
Sorry about the delay. Here's a snippet of my professionals json. Thanks for all the help. {"professionals": "[{\"model\": \"professionals.professional\", \"pk\": 1, \"fields\": {\"name\": \"professional14\", \"description\": \"testtest12345\", \"rating\": 5, \"image\": \"DP0119201620405230C_HjI6YVE.jpg\", \"video\": \"aswdawdawd\", \"professional_profile\": 2}}, {\"model\": \"professionals.professional\", \"pk\": 2, \"fields\": {\"name\": \"professional2\"}}]"}
However, that was with console.log(response). If I do console.log(response.professionals) I get undefined.
Great - since you used a django-serializer to to 'jsonify' your objects you'll need to parse the incoming json - see my edited answer above. You'll then need to grab the data from the json as needed - you have a few options for restructuring the professionals json using django-serializers - or you can write your own simple serializer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.