簡體   English   中英

使用 Javascript 或其他方法從字典中為 Django 模板中的 select 值設置動態值

[英]Set dynamic values from a dictionary for select values inside a Django template using Javascript or other method

我有三個連續的 select 選項,它們的值根據前面的 select 而變化。目的是使用這些 select 選項對產品進行分類。 第一個選項是根據產品的usagemodel值對產品進行分類。 如果選擇usage作為第一個select選項,則顯示填充有usage列表的第二個select ,該列表是Usage model 的所有對象,如果選擇model ,則填充 MainModel 885736168 的所有對象的MainModel是顯示,另一個select標簽被visually-hidden class 隱藏。

至此,我的代碼如下:

意見.py:

def get_common_queryset():
    usage_queryset = Usage.objects.all()
    main_model_queryset = MainModel.objects.all()
    sub_usage_queryset = SubUsage.objects.all()
    pump_type_queryset = PumpType.objects.all()
    queryset_dictionary = {
        "usage_queryset": usage_queryset,
        "main_model_queryset": main_model_queryset,
        "sub_usage_queryset": sub_usage_queryset,
        "pump_type_queryset": pump_type_queryset,
    }
    return queryset_dictionary

def solution_main(request):
    context  = get_common_queryset()
    return render(request, "solutions/solution_main.html", context) 

我的模板:

<div class="col-md-3 mx-md-5">
    <h2 class="h5 nm-text-color fw-bold mb-4">Choose usage or model:</h2>
    <select required aria-label="Select usage or model"
            id="usage_model_select" class="form-select" onchange="set_usage_or_model_dic()">
        <option>----</option>
        <option value="usage">Usage</option>
        <option value="model">Model</option>
    </select>
</div>

{#  usage or model select div #}
<div class="col-md-3 mx-md-5">

{#  usage select div #}
    <div class="usage visually-hidden" id="usage_div">
        <h2 class="h5 nm-text-color fw-bold mb-4">Select usage:</h2>
        <select required aria-label="Select usage" class="form-select"
                name="usage_select" onchange="set_sub_usage_list()" id="usage_select_id">
            <option selected>----</option>
            {% for usage in usage_queryset %}
                <option value="{{ usage.id }}">{{ usage.usage_name_fa }}</option>
            {% endfor %}
        </select>
    </div>

{#  model select div #}
    <div class="model visually-hidden" id="model_div">
        <h2 class="h5 nm-text-color fw-bold mb-4">Select model:</h2>
        <select required aria-label="Select model" class="form-select"
                name="model_select" onchange="set_pump_type_list()" id="model_select_id">
            <option selected>----</option>
            {% for model in main_model_queryset %}
                <option value="{{ model.id }}">{{ model.model_name_fa }}</option>
            {% endfor %}
        </select>
    </div>
</div>

{# select sub_usage or pump_type div #}
<div class="col-md-3 mx-md-5">

{#  sub_usage select div #}
    <div class="sub_usage visually-hidden" id="sub_usage_div">
        <h2 class="h5 nm-text-color fw-bold mb-4">Select sub-usage:</h2>
        <select required aria-label="Select sub_usage" class="form-select" name="sub_usage_select">
            <option selected>All sub-usages from this usage</option>
            {% for sub_usage in sub_usage_queryset %}
                <option value="{{ sub_usage.id }}">{{ sub_usage.sub_usage_name_fa }}</option>
            {% endfor %}
        </select>
    </div>

{#  model select div #}
    <div class="pump-type visually-hidden" id="pump_type_div">
        <h2 class="h5 nm-text-color fw-bold mb-4">Select pump type:</h2>
        <select aria-label="Select pump_type" class="form-select" name="pump_type_select">
            <option selected>All pump types of this model</option>
            {% for pump_type in pump_type_queryset %}
                <option value="{{ pump_type.id }}">{{ pump_type.type_name }}</option>
            {% endfor %}
        </select>
    </div>
</div>
<div>
    <input type="submit" value="Next" id="submit" class="btn btn-primary">
</div>


(我使用 JS 來顯示/隱藏特定的 div,刪除/添加visually-hidden類)

但是,我不想使用sub_usage_queryset = SubUsage.obects.all() ,我想看看在前一階段選擇了哪個usage (或model )並根據這個選擇填充下一個select

我想到的解決方案是,由於usage s 和main_model s 很少,我可以為每個創建一個字典,其中包含不同的usage s 或main_model s 作為鍵,並將它們的sub_usage s 或pump_type s 作為它們的值的列表. 作為usage示例:

sub_usage_list = {}
for usage in Usage.objects.all():
    usage_sub_usage_list = SubUsage.objects.filter(usage=usage)
    sub_usage_list[usage] = usage_sub_usage_list

因此sub_usage_list將包含每個usage作為鍵,並且該usagesub_usage s 作為該鍵值的列表。

我不知道這種方法是否正確,即使正確,我也不知道如何根據相關select選項中的選定值使用該詞典中的特定 sub_usage 列表。 我對 JS 不是很熟悉,所以非常感謝您的幫助和提示。

注意:如您所見,我正在使用服務器端渲染,所以我不知道如何在不刷新頁面的情況下執行此操作。

要在不刷新頁面的情況下實現您想要的效果,有必要使用 AJAX。

從您的模板開始。 由於您將根據選擇動態填充,因此沒有必要為每個 QuerySet 設置一個框。 您可以使用 JS 清除並重新填充它們。

模板.html:

<body>
    <div class="col-md-3 mx-md-5">
        <h2 class="h5 nm-text-color fw-bold mb-4">Choose usage or model:</h2>
        <select required aria-label="Select usage or model"
                id="usage_model_select" class="form-select" onchange="populate_lists()">
            <option value="" selected>----</option>
            <option value="usage">Usage</option>
            <option value="model">Model</option>
        </select>
    </div>
    
    {#  usage or model select div #}
    <div class="col-md-3 mx-md-5">
        {#  usage select div #}
        <div class="usage visually-hidden" id="usage_div">
            <h2 class="h5 nm-text-color fw-bold mb-4">Select options:</h2>
            <select required aria-label="Select usage" class="form-select"
                    name="usage_select" onchange="populate_lists()" id="select_options">
                <option value="" selected>----</option>
            </select>
        </div>
    </div>
    
    {# select sub_usage or pump_type div #}
    <div class="col-md-3 mx-md-5">
        {#  sub_usage select div #}
        <div class="sub_usage visually-hidden" id="sub_usage_div">
            <h2 class="h5 nm-text-color fw-bold mb-4">Sub selection:</h2>
            <select required aria-label="Select sub_usage" class="form-select" id="sub_usage_select" name="sub_usage_select">
                <option selected>All sub-selections</option>
            </select>
        </div>
    </div>

    <div>
        <input type="submit" value="Next" id="submit" class="btn btn-primary">
    </div>
</body>

templates.html <script> : ( CSRF with AJAX | Get Select element | Populate Select element | Clear Select element )

<script>
    function getCookie(name) {
        let cookieValue = null;
        if (document.cookie && document.cookie !== '') {
            const cookies = document.cookie.split(';');
            for (let i = 0; i < cookies.length; i++) {
                const cookie = cookies[i].trim();
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) === (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }

    // Clear SelectionBoxes
    function removeOptions(selectElement, initial) {
        var i, L = selectElement.options.length - 1;
        for(i = L; i >= 0; i--) {
            selectElement.remove(i);
        }
        var opt = document.createElement('option');
        opt.value = "";
        opt.innerHTML = initial;
        selectElement.appendChild(opt);
    }

    function populate_lists() {
        const url = '/solution/ajax/';
        const csrftoken = getCookie('csrftoken');

        var e = document.getElementById("usage_model_select");
        var selectedOption = e.value;
        if (selectedOption == "" ) {
            removeOptions(document.getElementById("select_options"), "----");
            removeOptions(document.getElementById("sub_usage_select"), "All sub-usages from this usage");
            return
        }

        var e = document.getElementById("select_options");
        var option = e.value;
        if (option == "" ) {
            option = null
        }
        
        // Send AJAX Request
        fetch(url, {
            method: 'POST',
            headers: {
                'X-CSRFToken': csrftoken,
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                "select": selectedOption,
                "option": option,
            }),
        })
        .then((response) => response.json())
        .then((data) => {
            var select = document.getElementById("select_options");
            removeOptions(select, "----");
            var selected_usage_name = null

            for (var i = 0; i<=data.select.length-1; i++){
                var opt = document.createElement('option');
                opt.value = data.select[i]['id'];
                opt.innerHTML = data.select[i]['name'];
                
                if (data.select[i]['id'] == data.selected_option) {
                    selected_usage_name = data.select[i]['name'];
                    opt.selected = true
                }
                select.appendChild(opt);
            }

            if (data.sub_select != null) {
                var select = document.getElementById("sub_usage_select");
                removeOptions(select, `All sub-usages from ${selectedOption} ${selected_usage_name}`);

                for (var i = 0; i<=data.sub_select.length-1; i++){
                    var opt = document.createElement('option');
                    opt.value = data.sub_select[i]['id'];
                    opt.innerHTML = data.sub_select[i]['name'];
                    select.appendChild(opt);
                }
                console.log(data.sub_select)
            }
            
        })
        .catch((error) => {
            console.error('Error:', error);
        });
    }
</script>

意見.py:

def solution_ajax(request):
    data = json.loads(request.body)
    sub_select = None

    if data['select'] == 'usage':
        select = list(Usage.objects.all().values())

        if data['option'] is not None:
            sub_select = list(SubUsage.objects.filter(usage__id=data['option']).values())

    elif data['select'] == 'model':
        select = list(MainModel.objects.all().values())

        if data['option'] is not None:
            sub_select = list(PumpType.objects.filter(model__id=data['option']).values())

    return JsonResponse({
        'select': select,
        'selected_option': data['option'],
        'sub_select': sub_select,
    })
    

def solution_main(request):
    return render(request, "solutions/solution_main.html") 

請注意,我做了一些額外的功能,例如清除選擇選項,但不是針對所有事件。

聖誕快樂。

django中有使用django-select2的方法。 請參閱這篇文章的解決方案: How to populate a select list in a Django Template dynamically using Javascript?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM