How to use database data in templates conditionally using JavaScript?

Hi there, I am working on an ecommerce store in Django. I want to know that how do I use the database data passed to templates using render() method, conditionally through JavaScript?

For example, let’s say I have a following models.py:

from django.db import models

class Suit(models.Model):
    title = models.CharField(max_length = 100, verbose_name = "Title")
    img = models.FileField(upload_to = 'suit-products/', null = True, verbose_name = "Picture")

    def __str__(self):
        return f"{self.title}"

class Buttoning(models.Model):
    title = models.CharField(max_length = 100, verbose_name = "Title")
    img = models.FileField(upload_to = 'buttonings/', null = True, verbose_name = "Picture")

    def __str__(self):
        return f"{self.title}"

and following views.py

from django.shortcuts import render

def index(request):
    suit_prods             = Suit.objects.all()
    buttoning = Buttoning.objects.all()

    context {
        "suit_prods": suit_prods,
        "buttoning": buttoning
    }

    return render(request, "index/index.html", context)

and following index.html (template):

    {% for element in suit_prods %}
        <li>
            <a href="#">
                <div id="menu">
                    <img src="{{ element.img.url }}" />
                    <span>{{ element.title }}</span>
                    <span></span>
                </div>
            </a>
        </li>
    {% endfor %}

Now what I want is, if the clicked element in the list items in index.html has the title as "two_piece_suit" then show items of {{ buttoning }} as a list, otherwise pass.

If I explain it more using some JS syntax, then I want following kind of behaviour:

<scrip>
    var suit_menu = document.getElementsByClassName("menu");
    for(var i = 0; i < suit_menu.length; i++) {
        if(suit_menu.text == "two_piece_suit") {
            {% for element in buttoning %}
                <li>
                    <a href="#">
                        <div id="buttoning">
                            <img src="{{ element.img.url }}" />
                            <span>{{ element.title }}</span>
                            <span></span>
                        </div>
                    </a>
                </li>
            {% endfor %}
        }
    }
</script>

@KenWhitesell any help in this?

Keep in mind that everything that Django renders in the template is work done on the server. Everything that JavaScript is working with is in the browser. JavaScript doesn’t “see” the context data, it only sees the html that is finally rendered. By the time that JavaScript is available and active, Django is done with the page and is no longer involved.

So, if you want JavaScript to work directly with the data, Django needs to provide it in a format that JavaScript can use - and usually the easiest way to do that is through JSON.

See the json_script tag docs for a way to do this, along with this blog post on Safely Including Data for JavaScript in a Django Template for an explanation as you why you want to do it that way instead of some other “solutions” you may find.

Another option is an AJAX-based solution. In your on-change handler for menu, issue an AJAX call back to the server (a view written just for this purpose) to retrieve the specific data needed and then inject the response into the page. This has the advantage of not rendering all data in the page when most of it likely isn’t going to be used.

A third approach would be to pre-render blocks of html and include them in the page in a hidden div (“display: none”). Your script could then just copy the contents of that div to the desired location based upon the selection. This has the downside of (most likely) creating the largest page sizes - this does not scale well as an option. If you have a small, well-constrained set of options, this can work for you. But if the set of options is going to grow over time, this is probably your worst choice.

2 Likes