如何使用 Javascript 动态填充 Django 模板中的 select 列表?
How to populate a select list in a Django Template dynamically using Javascript?
我最近一直在学习 Django 和 HTML,但我对 JavaScript 完全陌生。我正在尝试创建一个侧面带有过滤器菜单的数据库显示页面。对于此页面,我有以下代码:
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))
我的过滤器 HTML 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>
我可以很好地填写列表,但我希望能够更改它,以便在选择 Manufacturer
后打开 Type
下拉框时,我只能从 Manufacturer
.
中获得 Type
的列表
谢谢。
您好像在谈论 "chained dropdowns feature"。
在 Django 中,您可以使用 django-select2
库轻松完成。
https://django-select2.readthedocs.io/en/latest/extra.html#interdependent-select2
我相信您可以 google 在任何编程语言中,当然,在 Python + Django 中,有很多解决方案和方法。
我希望只是一些很好的示例文章:)
- https://simpleisbetterthancomplex.com/tutorial/2018/01/29/how-to-implement-dependent-or-chained-dropdown-list-with-django.html
- https://github.com/sibtc/dependent-dropdown-example
- https://www.devinterface.com/en/blog/how-to-implement-two-dropdowns-dependent-on-each-other-using-django-and-jquery
- http://sayhelloworld.co/dependent-dropdown-with-pre-checked-fields/
其他图书馆(来自google)
- https://pypi.org/project/django-clever-selects/
- https://github.com/jazzband/django-smart-selects
- https://github.com/s-block/django-chained-selectbox
- https://django-selectable.readthedocs.io/en/latest/advanced.html#chained-selection
编码愉快! :)
使用 Javascript,您可以在 select 元素上添加 event listeners
,这将触发对 python 后端的请求。但是,您必须编辑视图,使其 returns 只有数据(通常为 JSON 格式),以便了解您隐藏或不隐藏哪些选项。下面的代码假设视图 returns 是一个简单的列表,您可能需要对其进行编辑。
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";
}
}
}
}
});
我最近一直在学习 Django 和 HTML,但我对 JavaScript 完全陌生。我正在尝试创建一个侧面带有过滤器菜单的数据库显示页面。对于此页面,我有以下代码:
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))
我的过滤器 HTML 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>
我可以很好地填写列表,但我希望能够更改它,以便在选择 Manufacturer
后打开 Type
下拉框时,我只能从 Manufacturer
.
Type
的列表
谢谢。
您好像在谈论 "chained dropdowns feature"。
在 Django 中,您可以使用 django-select2
库轻松完成。
https://django-select2.readthedocs.io/en/latest/extra.html#interdependent-select2
我相信您可以 google 在任何编程语言中,当然,在 Python + Django 中,有很多解决方案和方法。
我希望只是一些很好的示例文章:)
- https://simpleisbetterthancomplex.com/tutorial/2018/01/29/how-to-implement-dependent-or-chained-dropdown-list-with-django.html
- https://github.com/sibtc/dependent-dropdown-example
- https://www.devinterface.com/en/blog/how-to-implement-two-dropdowns-dependent-on-each-other-using-django-and-jquery
- http://sayhelloworld.co/dependent-dropdown-with-pre-checked-fields/
其他图书馆(来自google)
- https://pypi.org/project/django-clever-selects/
- https://github.com/jazzband/django-smart-selects
- https://github.com/s-block/django-chained-selectbox
- https://django-selectable.readthedocs.io/en/latest/advanced.html#chained-selection
编码愉快! :)
使用 Javascript,您可以在 select 元素上添加 event listeners
,这将触发对 python 后端的请求。但是,您必须编辑视图,使其 returns 只有数据(通常为 JSON 格式),以便了解您隐藏或不隐藏哪些选项。下面的代码假设视图 returns 是一个简单的列表,您可能需要对其进行编辑。
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";
}
}
}
}
});