A path (perhaps the most obvious) is the use of javascript, in the first select you arrow an onchange that calls a function to "popular" the second select.
Has a demo here which fits perfectly with your question, just make the appropriate adaptations. 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 became so extensive, go straight down in 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 function populateCountries it changes the onchange of countries select to call the function populating the states (populateStates) sending the objects to it.
Try to adapt, if you can not, post here the problem.
Edited from 20/03/2017 ( from here)
Ok, As agreed (in the comments of that reply), I spent my Saturday to create my own version to try to answer what was requested. The explanation here is only to clarify how the process was to take the database data, pass to the Jango template and, finally, deliver to the JS. The complete and functional project (in Django) can be downloaded in this github.
In the example we will use a register of vehicles in a fleet (see that I was not busy with recording the data in the database, focused only on what was requested in the question). There are two main models for the demonstration, one for the brands (Brands) and the other for the models of the vehicles (Car).
py.models
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 artificial function was used in the __str__ function of the model Car, so that the call to Objects.all() returns a dictionary with the name and brand of the models.
With the models ready, we go to the view, which is the main function 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 does, essentially the seginte:
- Select from models the Brand objects (tags) and assign to the variable
Brands;
- Select from models the Car objects (models) and assign to
variable Cars;
- Convert the two variables to JSON format;
- Render a regcar template.
The template is very simple, has only one div with the two selects, properly identified by the ID. Although it is presented separately here, the JS script is included in the template, so that it is loaded with it (could be via a block, WYL.). In the load process, select identified as '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>
<link href="{% 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 with the template at this time
two variables are created that receive the JSON values that were sent to the template by the view, see that just do the assignment normally, as if it were in python or in the template itself. In addition to creating these variables, the brand select (Brand) onchange event 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 function populateBrand() is called to fill the select of the marks (Brand).
<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:
That same question in Stoen:
https://stackoverflow.com/a/43074402/2879341
Full project in Django:
http://jsfiddle.net/bdhacker/eRv2W/
Codepen version:
https://codepen.io/Sidon/pen/yMpbKg
Fiddle version:
https://jsfiddle.net/Sidon/6m1nf0zu/62/
If it is during client-side interaction, no request is made to the server between the first selection and the population of the second select you should use is javascript, with ajax if necessary
– Miguel
Both
select
have the sameid
. Pay attention to that.– Woss