Guide to dynamically populating a select dropdown in a Django template with Javascript

Recently, I started learning Django and HTML, but JavaScript is still quite new to me. I'm working on creating a database display page with a filter menu on the side. Here is the code for this particular page:

Model.py:

class Part(models.Model):
    PartID = models.AutoField(primary_key=True, unique=True)
    SiteID = models.ForeignKey('Site', on_delete=models.CASCADE, null=True)
    Comment = models.CharField(max_length=255, blank=True)
    Subtype = models.ForeignKey('Subtype', on_delete=models.CASCADE, null=True)
    Location = models.CharField(max_length=255, blank=True)
    ConnectedTo= models.ManyToManyField('self', null=True)
    BatchNo = models.CharField(max_length=32, blank=False, null=True)
    SerialNo = models.CharField(max_length=32,blank=True)
    Manufacturer = models.CharField(max_length=32, blank=False, null=True)
    Length = models.FloatField(blank=True, null=True)
    InspectionPeriod = models.IntegerField(blank=True, null=True)
    LastInspected = models.DateField(blank=True, null=True)
    InspectionDue = models.CharField(max_length=255, blank=True)

View.py:

@login_required(login_url='/accounts/login/')
def sites(request, site):

    siteselected = site
    warnings = 0
    expired = 0
    good = 0
    PartsAtSite = Part.objects.filter(SiteID = siteselected)
    TypesList = Type.objects.values_list('TypeName', flat=True).distinct()
    InspectionList = Part.objects.values_list('InspectionPeriod', flat=True).distinct()
    LengthList = Part.objects.values_list('Length', flat=True).distinct()
    LocationList = Part.objects.values_list('Location', flat=True).distinct()
    ManufacturerList = Part.objects.values_list('Manufacturer', flat=True).distinct()

    for part in PartsAtSite:
        if part.LastInspected == None:
            part.InspectionDue = "Yes"
            expired = expired + 1

        else:
            Deadline = part.LastInspected + timedelta(days=part.InspectionPeriod)

        if datetime.now().date() > Deadline:
            part.InspectionDue = "Yes"
            expired = expired + 1

        elif datetime.now().date() > (Deadline - timedelta(days=30)):
            part.InspectionDue = "<30 Days"
            warnings = warnings + 1
        else:
            part.InspectionDue = "No"
            good = good + 1
    part.save()

    context = {
        'TypesList': TypesList,
        'InspectionList': InspectionList,
        'LengthList': LengthList,
        'LocationList': LocationList,
        'ManufacturerList': ManufacturerList,
        'PartsAtSite': PartsAtSite,
        'expired': expired,
        'warnings': warnings,
        'good': good,
        'SiteName': Site.objects.get(SiteID = siteselected).SiteName,
        'SiteNo': Site.objects.get(SiteID = siteselected).SiteID,
    }

template = loader.get_template('myproject/sites.html')
return HttpResponse(template.render(context, request))

And the HTML for my filter div:

<div id="filterdiv" class="dark">
    <center><h3>Filters</h3></center>
    <br>

    <center>Type</center>
    <select name="Types">
        <option>All</option>
        {% for types in TypesList %}
            <option>{{types}}</option>
        {%endfor%}
    </select>
    <br>
    <br>

    <center>Inspection Period</center>
    <select name="Inspection Period">
        <option>All</option>
        {% for inspections in InspectionList %}
            <option>{{inspections}}</option>
        {%endfor%}
    </select>
    <br>
    <br>

    <center>Length</center>
    <select name="Length">
        <option>All</option>
        {% for lengths in LengthList %}
            <option>{{lengths}}</option>
        {%endfor%}
    </select>
    <br>
    <br>

    <center>Location</center>
    <select name="Location">
        <option>All</option>
        {% for locations in LocationList %}
            <option>{{locations}}</option>
        {%endfor%}
    </select>
    <br>
    <br>

    <center>Manufacturer</center>
    <select name="Manufacturer">
        <option>All</option>
        {% for manufacturers in ManufacturerList %}
            <option>{{manufacturers}}</option>
        {%endfor%}
    </select>
    <br>
    <br>
    <button>Apply Filter (TODO)</button>
    <button>Reset Filters (TODO)</button>
</div>

I have successfully populated the lists, but my goal now is to modify it so that when I select a Manufacturer and then open the Type dropdown menu, only the list of Types from that specific Manufacturer are shown.

Thank you.

Answer №1

It seems like you're interested in the concept of "chained dropdowns feature".

If you're working with Django, implementing this can be made easy with the help of the django-select2 library.

You can explore various solutions and approaches for achieving this functionality in different programming languages, particularly in Python + Django.

Here are a few helpful articles that I recommend:

  • Tutorial - Implementing Dependent or Chained Dropdown List with Django
  • Dependent Dropdown Example on GitHub
  • How to Implement Two Dependent Dropdowns using Django and jQuery
  • Dependent Dropdown with Pre-Checked Fields

Additionally, you can explore other libraries available on the web:

Happy coding! :)

Answer №2

One way to enhance the functionality of your select elements with JavaScript is by adding event listeners that will trigger requests to your Python backend. To achieve this, you will need to modify the view to return data in JSON format so you can determine which options to display or hide. The following code assumes that the view returns a basic list, which may require adjustments.

document.getElementById("yourSelect").addEventListener("change", function () {
    // Add an event handler for the change event
    let req = new XMLHttpRequest(),
        other_select = document.getElementById("anotherSelect");
    req.open("POST", "yourUrl", true);
    // You will need to use json.loads in Python code
    req.send(JSON.stringify({value: this.value}));
    req.onreadystatechange = function (res) {
        if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
            // Once the request is complete and the server returns a success code
            for (let i in other_select.children){
                let opt = other_select.children[i];
                if(res.indexOf(opt.value) > -1 ){
                    // Show the option if previously hidden
                    opt.style.display = "block";
                }else{
                    // Hide the option
                    opt.style.display = "none";
                }
            }
        }
    }
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Integrate a button following the first paragraph exclusively when there are two or more paragraphs present

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> jQuery(document).ready(function($) { if ( $('p').length < 1 ) { $('p:last-child').after('<div id="toggle" class="btn"> ...

Updating route in AngularJS does not populate data (ngRepeat)

Just starting out and trying to figure things out, so bear with me if this is a basic issue. I have two routes set up. localhost:3000 displays a list of objects, while localhost:3000/:slug shows detailed information about a specific product. The initial ...

Transforming JSON data into a dynamic Tableview

I've been experimenting with this issue for quite some time now, but I can't seem to find a solution. My API returns tasks in JSON format. When I print the data using Ti.API.info(this.responseText), it looks like this: [INFO] [{"created_at":"20 ...

Creating a filter using radio input in HTML and CSS is a simple and

Currently, I am delving into the world of Javascript and React, but I have hit a roadblock. My goal is to create a Pokedex, yet I am encountering some difficulties. I have implemented Radio Inputs to filter Pokemon by generation, but I am struggling with ...

Insert a hyperlink button using InnerHtml

I am facing an issue with displaying a list item that contains a tab and a link button: <li runat="server" id="liActivityInvoices"><a href="#tabActivityInvoices">Invoices</a><asp:LinkButton runat="server" ID="btnLoadInvoice" OnClick=" ...

Ways to access a particular property of a child component object from the parent component

Is there a way to access a child component's "meta" property from the parent component without using the emit method? I am aware of the solution involving an emit method, but I'm curious if there is a simpler approach to achieving this. // Defau ...

When using NextJS with next-i18next and Firebase functions, all pages are redirected to a 404 error page if the locale is included

I have implemented next-i18next with Next.js in a setup that involves SSR deployed to Firebase functions. I followed the guidelines provided in this documentation https://github.com/i18next/next-i18next During development, everything functions correctly, ...

A guide to implementing accurate pagination in Vue.js 2

I'm encountering an issue while setting up pagination with Vue. My goal is to load new tasks from jsonplaceholder when the numbers on the buttons are clicked. I have managed to successfully load the first and second pages. I believe this is directly ...

Alter the database field value in MongoDB without relying on req.body inputs

Is there a way to update a value from X post in my database without using a form in my front end app? I need to trigger the update through a button click instead. Typically, we use req.body to send data from a form. But how do I handle updating the value ...

What could be the reason for express-validator's inability to identify missing fields during the validation of XML input

My server, based on Express, is set up to parse XML instead of JSON using body-parser-xml. To validate the input body, I am using express-validator as shown in the following simplified example: router.post("/", body('session.credential[0].$.usern ...

The appearance of a slide-in hamburger menu causes the horizontal scrollbar to appear

To create a hamburger menu that slides in from the right when clicking the icon, follow this code snippet. Here is the main menu code where it is initially translated to the right by 100% and on icon click, it comes back on screen with a translation of 0% ...

Using JavaScript, divide a string containing elements of unknown length that may be adjacent based on their type

If I have a string representing an SVG path like: "M72 0v754h405v-86h-311v-211h302v-86h-302v-285h311v-86h-405z" My goal is to transform it into an array where each element consists of either a letter or a positive/negative number. For example: [ ...

Tips for choosing a specific point on a Vuetify <v-slider> using Cypress

Currently, I am exploring how my application responds when a user interacts with a specific area on a basic Vuetify <v-slider>. How can I replicate this scenario in a Cypress integration test effectively? For instance, to click on the center of the ...

FitText.js malfunctioning

I'm currently experimenting with using FitText.js to dynamically adjust the size of headlines to fit within the limits of the browser width. Interestingly, while this script successfully resizes the text in multiple sections of my website, it seems t ...

Error in Django: When performing an exact lookup, the QuerySet value must be limited to one result using slicing

I keep encountering an issue when attempting to create an object using data from a CSV file, and the error message reads: "The QuerySet value for an exact lookup must be limited to one result using slicing." This error seems to be originating f ...

Tips for utilizing Sass and CSS Modules within create-react-app

I've been using FileName.module.scss to style my react elements like this: // Component styling with SCSS import React from "react"; import Aux from '../../hoc/Aux'; import classes from './Layout.module.scss'; const lay ...

Rendering on the server with React, React-Router, and Express

I'm currently in the process of setting up server-side rendering for my react application and I'm utilizing the fantastic react-router module to enable it to manage non-js scenarios (such as certain crawlers or users with javascript disabled). Ne ...

Adding data to an AngularJS template

I am encountering an issue with a flag that I am toggling between true and false to alter the display of certain elements on my page. While it works outside of the template, integrating this value into the template itself has proven challenging. restrict: ...

What are some ways to enhance the efficiency of the random blog post redirection within my Django application?

If you're looking for a unique way to add a random blog post link to your website, I have the code that worked for me. Initially, I encountered a problem with a 'QuerySet' object not having an attribute 'slug', but I managed to fin ...

Registration in Django using rest-auth and allauth can be done with just email, first name and last name, eliminating the need

I have implemented login and registration functionality in my Django app using django-rest-auth and allauth. Interestingly, I did not have to write any additional code for handling the login or registration process. Registration works smoothly with email a ...