Сохранение нескольких GET-параметров в URL Django

В моем проекте django есть страница, отображающая список времен. На этой странице есть 3 GET формы, которые предназначены для:

  • Разбор страниц

  • Выбор данных графика

  • Сортировка элементов

Если пользователь должен выбрать поле во всех этих формах, URL должен выглядеть примерно так:

http://127.0.0.1:8000/watchlist/?page=1&graph_data=price&sort=quantity_desc

Но когда пользователь отправляет одну из этих форм, он сохраняет только этот GET-параметр в URL. например:

выбирает страницу = 2

http://127.0.0.1:8000/watchlist/?page=2

selects sort = quantity_asc

http://127.0.0.1:8000/watchlist/?sort=quantity_asc

Параметр страницы перезаписывается, когда оба параметра должны присутствовать в URL. Как сохранить несколько GET-параметров в URL?

views.py

def watchlist(request):

    #get requests
    graph_metric = request.GET.get("graph-data-options", "avg_price")
    page = int(request.GET.get("page", 1))
    sort_field = request.GET.get("sort-field", "avg_price-asc")

return render(request, "App/watchlist.html", context=context)

html

<!-- Page number -->
<form id="page-buttons-form" action="{% url 'watchlist' %}" method="GET">
    {% for page_button in num_pages %}
        <input name="page" type="submit" value="{{page_button}}">
    {% endfor %}
</form>

<!-- Sort items -->
<form id="sort-form" action="{% url 'watchlist' %}" method="GET">
    <label for="sort-field">Sort:</label>
    <select onchange="this.form.submit()" name="sort-field">
        {% for sort in sort_options %}
            <option value="{{sort.value}}">{{sort.text}}</option>
        {% endfor %}
    </select>
</form>

<!-- Graph data -->
<form action="{% url 'watchlist' %}" method="GET">
    <label for="graph-data-options">Graph Data</label>
    <select onchange="this.form.submit()" name="graph-data-options">
        {% for graph_option in graph_options %}
            <option value="{{graph_option.value}}">{{graph_option.text}}</option>
        {% endfor %}
    </select>
</form>

Это пробный вариант, демонстрирующий, как можно сохранить GET-параметры при отправке различных форм. Каждая форма запускает функцию fillHiddenFields перед отправкой, вставляя существующие параметры URL в скрытые поля.

Примечание: Очевидно, это не работает как сниппет StackOverflow, поэтому вам придется выполнить это на локальной машине.

function fillHiddenFields(event){
    // extract query params from URL
    const urlSearchParams = new URLSearchParams(window.location.search);
    const params = Object.fromEntries(urlSearchParams.entries());
    // find hidden fields in form
    let form = event.target;
    const hiddentElmts = form.querySelectorAll('input[type=hidden]');
    // update hidden fields with URL query params
    for(let elmt of hiddentElmts){
        if(elmt.name in params){
            elmt.value = params[elmt.name];
        }
    }
    // console.log form data to check that hidden fields are updated
    let formdata = new FormData(form);
    console.log(Object.fromEntries(formdata));
}
<body>
    <form id="form1" action="javascript:void(0)" method="GET" onsubmit="fillHiddenFields(event)">
        <input type="text" name="field1" value="Field 1">
        <input type="hidden" name="field2" value="">
        <input type="submit" value="Submit">
    </form>
    <form id="form2" action="javascript:void(0)" method="GET" onsubmit="fillHiddenFields(event)">
        <input type="hidden" name="field1" value="">
        <input type="text" name="field2" value="Field 2">
        <input type="submit" value="Submit">
    </form>
</body>

Чтобы сохранить несколько GET-параметров в URL, вы можете включить текущие GET-параметры в атрибут action формы. Один из способов сделать это - использовать словарь request.GET для построения URL.

В вашем файле views.py вы можете изменить функцию watchlist следующим образом:

def watchlist(request):
    #get requests
    graph_metric = request.GET.get("graph-data-options", "avg_price")
    page = int(request.GET.get("page", 1))
    sort_field = request.GET.get("sort-field", "avg_price-asc")
    context = {...}
    context['url_params'] = request.GET.copy()
    context['url_params'].pop("page", None)
    return render(request, "App/watchlist.html", context=context)

Затем в своем шаблоне вы можете включить текущие параметры GET в атрибут action формы следующим образом:

<form id="page-buttons-form" action="{% url 'watchlist' %}?{% for key, value in url_params.items %}{{key}}={{value}}&{% endfor %}" method="GET">
    {% for page_button in num_pages %}
        <input name="page" type="submit" value="{{page_button}}">
    {% endfor %}
</form>
Вернуться на верх