2

I am new to jQuery.

I tried getting/summing some items from my django views in jQuery. This is what I have:

$(document).ready(function()
{
    var sch = $('#sch-books');
    var gov = $('#gov-books');
    var total = sch.val() + gov.val();
    $('#total').text("Total : " + total); 

});

My template has this:

<div id="sch-books" class="h6 mb-1">School copies - <b>{{ s_books.count }}</b></div>
<div id="gov-books"class="h6 mb-1">Govt copies - <b>{{ g_books.count }}</b></div>
<div id="total"></div>

It displays Total :

May someone help me get it right..

9
  • 2
    div doesn't have value, you need to parse only int Commented Nov 20, 2021 at 10:48
  • 1
    Trust me, a simple operation like adding two numbers will not make your website slow. Much longer it will take to send your HTTP response to the client. Commented Nov 20, 2021 at 11:01
  • 1
    you can use django add template tag docs.djangoproject.com/en/3.2/ref/templates/builtins/#add Commented Nov 20, 2021 at 11:14
  • 1
    try this : {{ s_books.count|add:g_books.count }} Commented Nov 20, 2021 at 11:15
  • 1
    @rahul.m - Oh wow, add does look promising. Commented Nov 20, 2021 at 11:19

4 Answers 4

3

Instead of involving the js script, I will recommend creating total_value on the Django side and moving it to the template.

<div class="h6 mb-1" data-count="{{ s_books.count }}">School copies - <b>{{ s_books.count }}</b></div>
<div class="h6 mb-1" data-count="{{ g_books.count }}">Govt copies - <b>{{ g_books.count }}</b></div>
<div>{total_count}</div>

I am not sure which way you follow to render the template, but should look at this one

# views.py
from django.shortcuts import render

def render_users(request):
    g_books = {}
    s_books = {}

    context = {
        "g_books": g_books,
        "s_books": s_books,
        "total_count": g_books.count + s_books.count
    }

    return render(request, 'books.html', context)
Sign up to request clarification or add additional context in comments.

2 Comments

And/or could Rahul's idea for add work?
Right, it also will work. To make it easier to debug I prefer to keep it in the view instead of the template. Cause we can add the breakpoint inside the view, but can not do it in the template.
3

you can try to use django-mathfilter for this purpose.because javascript can be disabled by the user and django-mathfilter is so powerfull.

$ pip install django-mathfilters

Then add mathfilters to your INSTALLED_APPS.

then in you template you can just do something like this.

{% load mathfilters %}
........
{% with s_books.count as s_book and g_books.count as g_book %} 
<div id="sch-books" class="h6 mb-1">School copies - <b>{{ s_book }}</b></div>
<div id="gov-books"class="h6 mb-1">Govt copies - <b>{{ g_book }}</b></div>
<div id="total">{{ s_book|add:g_book }}</div>
{% endwith %}

for more information read this https://pypi.org/project/django-mathfilters/

Comments

3

val() returns value attribute like in <input type="text" value=something/> and html() returns the content (innerHTML) of selected element.

So modify your codes like this and you are good to go. (I am assuming that django returns a numeric value in {{ s_books.count }} and {{ g_books.count }}).

$(document).ready(function()
{
    var sch = $('#sch-books b').html(); // added b element  and calling html()
    var gov = $('#gov-books b').html(); // added b element  and calling html()
    
    var total = parseInt(sch) + parseInt(gov); // converted the string into number using parseInt()

    $('#total').text("Total : " + total); // worked

});

Comments

2

Preface: I would suggest you handle this in the template, there are now two answers showing you how (here and here). (I don't do Django.) Beware that doing this in client-side code will cause the <div id="total"></div> to appear blank very briefly and then get filled in with the number. If that element is in view when the page loads, the users will see that flicker — even if they can't see exactly what it was that flickered (which can be irritating). Avoiding that by doing it in the Django view would probably better.

But re your client-side code:

div elements don't have a value, they have textContent and innerHTML (see this question's answers for details). But the contents of those div elements will have lots of things in them other than the numbers you're looking for. While you could isolate the number from the text (or retrieve it just from the b element within the div), those are both fragile solutions that will break if someone changes the template in seemingly-innocent ways.

If you really want to handle this with client-side code, store the values you want in data-* attributes on the div elements:

<div id="sch-books" class="h6 mb-1" data-count="{{ s_books.count }}">School copies - <b>{{ s_books.count }}</b></div>
<div id="gov-books" class="h6 mb-1" data-count="{{ g_books.count }}">Govt copies - <b>{{ g_books.count }}</b></div>
<div id="total"></div>

Then grab that data-* attribute:

$(document).ready(function() {
    const sch = +$("#sch-books").attr("data-count");
    const gov = +$("#gov-books").attr("data-count");
    const total = sch + gov;
    $("#total").text(`Total : ${total}`); 
});

8 Comments

Of course, the solution with data attributes will work, but I think the person who asked the question does not have much experience and we should not suggest the solution that more experienced developers will do. The solution with the Django template looks great :) I think it should be better than involving JS.
@KrystianSztadhaus - Perhaps you could post the way to do it in the template. I had to remove mine because I found this telling me that it didn't work. I agree that doing it in the template would probably be better.
You are right, sorry for that :)
@KrystianSztadhaus - Meh, I was being overly touchy. :-) Thanks.
@amadousow - If you have a Django-based solution, by all means, please post it. :-) (I don't do Django, so I can only help with the client-side code the OP was trying to use -- but I think the problem would be better solved with Django.)
|

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.