Popular select a partit from another select using python and django

1

Good night, I'm new to the forum, and I started doing a small project with python and django. I'm trying to fill a select according to the selected option in another. But since I'm a beginner, I do not know how to do that.

<div class="form-group col-sm-4">
   <label id="lb-shift">Turno</label>
       <select id="p-shift" class="form-control">
        {% for course in courses %}
           <option value="{{ course.id }}">{{ course.name }}</option>
        {% endfor %}
       </select>
</div>
<div class="form-group col-sm-4">
    <label id="lb-shift">Turno</label>
    <select id="p-shift" class="form-control">
        {% for turm in turms %}
             {% if turm.idCourse == "valor do outro select"%}
                <option value="{{ turm.id }}">{{ turm.name }}</option>
             {% endif %}
        {% endfor %}
    </select>
</div>
    
asked by anonymous 27.02.2017 / 00:10

2 answers

1

To understand why you can not implement the way you tried, just with Python, you need to understand the differences between frontend and backend . Maybe this discussion help you with something.

But basically Python runs on the backend , delivering the HTTP response to the client, in this case the browser. After delivery of the response, execution is terminated and therefore Python will no longer respond to page changes, such as selecting an item in select . You can make it respond to an asynchronous request via AJAX, but the easiest one in your case is to implement logic in a different way with JavaScript.

First, you define, in the second select , a data-course attribute for each option , storing the value of turn.idCourse , as follows:

<div class="form-group col-sm-4">
   <label id="lb-shift">Turno</label>
       <select id="p-shift" class="form-control">
        {% for course in courses %}
           <option value="{{ course.id }}">{{ course.name }}</option>
        {% endfor %}
       </select>
</div>
<div class="form-group col-sm-4">
    <label id="lb-shift">Turno</label>
    <select id="t-shift" class="form-control">
        {% for turm in turms %}
            <option data-course="{{ turn.idCourse }}" value="{{ turm.id }}">{{ turm.name }}</option>
        {% endfor %}
    </select>
</div>

And, with JavaScript, you observe the onchange event of the first select , retrieve the selected value, and display, in the second select , only the option whose data-course is equal to the value selected.

  

The HTML code used below is a representation close to the HTML that Python would generate dynamically and is only used to reproduce the example here.

$(function () {

  // Oculta as opções do segundo select:
  $("#t-shift option").hide();
  
  // Observa o evento change do primeiro select:
  $("#p-shift").on("change", function () {
  
    // Recupera o valor selecionado:
    let course = $("#p-shift").val();
    
    // Oculta as opções atuais:
    $("#t-shift option").hide();
    
    // Exibe as opções conforme a seleção:
    $("#t-shift option[data-course="+ course +"]").show();
  
  });

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><divclass="form-group col-sm-4">
  <label id="lb-shift">Course</label>
  <select id="p-shift" class="form-control">
    <option selected disabled>Selecione</option>
    <option value="1">Course 1</option>
    <option value="2">Course 2</option>
    <option value="3">Course 3</option>
   </select>
</div>
<div class="form-group col-sm-4">
  <label id="lb-shift">Turn</label>
  <select id="t-shift" class="form-control">
    <option selected disabled>Selecione</option>
    <option data-course="1" value="1">Turn 1</option>
    <option data-course="2" value="2">Turn 2</option>
    <option data-course="3" value="3">Turn 3</option>
    <option data-course="1" value="4">Turn 4</option>
    <option data-course="2" value="5">Turn 5</option>
    <option data-course="3" value="6">Turn 6</option>
  </select>
</div>

Make sure that by selecting course 1, only the Turn 1 and Turn 4 options are available. When you select course 2, the options Turn 2 and Turn 5 are available. Finally, when selecting course 3, the options Turn 3 and Turn 6 will be.

    
15.03.2017 / 23:45
0

A path (perhaps the most obvious) is to use javascript, in the first select you arrow an onchange that calls a function to "popular" the second select.

Have a demo here that fits your question perfectly, just make the appropriate adjustments. Do not be intimidated by the code in the javascript section (bottom). The guy created arrays with several countries / states of the world, so it was so extensive, go straight down the two functions (populateStates and populateCountries).

Basically, he did the following, calls these two functions when the page is loaded and populates the two selects (as the country has not yet been chosen, the states select is empty), on that occasion, in the populateCountries function it changes the select onchange from countries to call the function that populates states (populateStates) by sending objects to it.

Try to adapt, if you can not, post here the problem.

  

Edited from 03/20/2017 (from here)
  Ok, As combined (in the comments of this answer), I spent my Saturday to create my own version to try to answer what was requested. The explanation here is only to elucidate how the process was to get the database, go to the django template and, finally, deliver it to JS. The project (in Django), complete and functional can be downloaded in this repo github .

In the example we will use a vehicle register in a fleet (see that I did not take care of recording the data in the bank, I focused only on what was requested in the question). There are two main demo models, one for Brands and one for Car Models.

models.py

from django.db import models
import json

class Brand(models.Model):
    company_name = models.CharField(max_length=100)

    def __str__(self):
        return self.company_name

class Car(models.Model):
    brand = models.ForeignKey(Brand)
    name = models.CharField(max_length=100)

    def __str__(self):
        return {'name': self.name, 'brand': self.brand.company_name}

It is important to note that an artifice was used in the __str__ function of the Car model, so that the call to objects.all () returns a dictionary with the name and brand of the models.

With the models ready, let's take a look at what the main function is to make the data available to the template and, consequently, to JS.

import json
from django.shortcuts import render
from .models import Brand, Car

def regcar(request):
    brands = Brand.objects.all()
    cars = Car.objects.all()
    dcars = {}
    for car in cars:
        brand = str(car.brand)
        if brand in dcars:
            dcars[brand].append(car.name)
        else:
            dcars[brand] = [car.name]
    cars = json.dumps(dcars)
    brands = json.dumps([str(b) for b in brands])
    return render(request, 'core/regcar.html', {'brands': brands, 'cars': cars})

This view essentially makes the following:

  • Select models from Brand objects and assign them to the variable brands;
  • Selects models of Car objects and assigns them to variable cars;
  • Converts the two variables to the JSON format;
  • Renders the template regcar.

The template is very simple, it has only one div with the two selects, duly identified by ID. Although presented here separately, the JS script is included in the template, so it can be loaded along with it (it could be through a block, WYL.). In the loading process, the select labeled 'brand' will be loaded by a JS function.

{% load staticfiles %}

<!DOCTYPE html>
<html lang="pt-br">
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script><linkhref="{% static "css/style.css" %}" rel="stylesheet">
        <meta charset="UTF-8">
        <title>Populating a Select with Django</title>
    </head>

    <body>

        <h1>Populate one dropdown based on selection in another.</h1>
        <p>Change the contents of dropdown Car based on the selection in dropdown Brand, using Django + Javascript:</p>

        <div class="select-style">
            <br />Brand:
            <select required id="brand">
            </select>

            <br />
            <br />Car:
            <select id="car" >
            </select>
        </div>


    </body>
</html>

The javascript code is loaded along with the template, at that time two variables are created that receive the JSON values that were sent to the template by the view, see that it is enough to do the assignment normally, as if it were in python or in the template itself. In addition to the creation of these variables, the onchange event of the select of the tags (brand) is directed to the populateCar () function, where the select whose id = car (car models) is populated every time the select brand onchange is modified. Finally, the populateBrand () function is called to populate the select of the (brand) tags.

<script language="javascript">
    $('#brand').change(function() {populateCar()});
    var cars = {{ cars|safe }}
    var brands = {{ brands|safe }}
    populateBrand();

    function populateBrand() {
        $("#brand").empty();
        $("#brand").append('<option value="" disabled selected>Select your option</option>');
        $.each(brands, function(v) {
            $('#brand')
                .append($("<option></option>")
                .attr("value", brands[v])
                .text(brands[v]));
        })
    }

    function populateCar(event) {
        brand = $("#brand option:selected" ).text();
        $("#car").empty();

        $("#car").append('<option value="" disabled selected>Select your option</option>');
        for (let [b, bcars] of Object.entries(cars)) {
            if (b==brand) {
                for (car in bcars) {
                    $('#car')
                        .append($("<option></option>")
                        .attr("value", bcars[car])
                        .text(bcars[car]));
                }
            }
        }

    }

</script>

Layout (Firefox)

Links:

ThissameissueinSTOen:
link

Complete project in Django:
link

Codepen version:
link

Fiddle Version:
link

    
15.03.2017 / 22:44