如何使用 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 中,有很多解决方案和方法。

我希望只是一些很好的示例文章:)

其他图书馆(来自google)

编码愉快! :)

使用 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";
                }
            }
        }
    }
});