Reputation: 459
I've recently been learning Django and HTML but I'm completely new to JavaScript. I'm having a go at creating a database display page with a filter menu at the side. For this page I have the following code:
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 am able to fill the lists just fine, but I want to be able to change it so that when I open the Type
drop down box after selecting a Manufacturer
, then I only get offered a list of Type
s from that Manufacturer
.
Thanks.
Upvotes: 0
Views: 2907
Reputation: 1910
Using Javascript, you could add event listeners
on your select elements that will trigger a request to your python backend. However you will have to edit the view so that it returns only data (usually in JSON format) in order to know which options you hide or not. Below code suppose that the view returns a simple list, you'll probably have to edit it.
document.getElementById("yourSelect").addEventListener("change", function () {
// add a handler to 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) {
// the request is done and server returned 200 success code
for (let i in other_select.children){
let opt = other_select.children[i];
if(res.indexOf(opt.value) > -1 ){
// shows the option if previously hidden
opt.style.display = "block";
}else{
// hides the option
opt.style.display = "none";
}
}
}
}
});
Upvotes: 0
Reputation: 3981
It looks like you are talking about "chained dropdowns feature".
In Django you can do it using django-select2
library easy.
https://django-select2.readthedocs.io/en/latest/extra.html#interdependent-select2
I am sure you can google a lot of solutions and methods of how to do it in any programming language and, of course, in Python + Django.
Just a few good examples articles from me I hope :)
Other libraries (from google)
Happy coding! :)
Upvotes: 3