Как лучше всего сохранять GET-параметры в django?

У меня есть ListView, который я отображаю с помощью элемента HTML <table>. Каждый столбец - это поле модели, а каждая строка - это конкретный экземпляр модели.

Для этого представления я реализовал поиск по нескольким полям модели (через GET форму с параметром запроса search), фильтрацию по каждому полю модели (через GET формы с параметрами запроса filter--{{ field.name }}-{{ filter-type }}) и упорядочивание по нескольким полям (через параметр запроса order). Я планирую добавить пагинацию и возможность для пользователя устанавливать размер страницы (так что скоро появятся еще два параметра запроса).

Мой вопрос: есть ли простой подход к сохранению существующих неизменных значений GET как в якорях, так и в формах GET?

Для контекста:

Все три могут быть активны одновременно, поэтому пути могут выглядеть как:

/example/
/example/?filter--service_expires_at-datetime_from=2024-02-27T09%3A31&filter--service_expires_at-datetime_to=
/example/?filter--username-icontains=abc&search=test
/example/?order=-username,service_expires_at&search=test&filter--username-icontains=abc

Поиск и фильтры имеют как ссылки (для очистки поиска или конкретного фильтра), так и GET-формы (для установки поиска или конкретного фильтра). Order имеет ссылки, которые изменяют GET-параметр order, чтобы добавить сортировку ASC или DESC (или удалить обе) по определенному столбцу.

Моя проблема в том, что сохранение GET-параметров стало довольно громоздким - например, когда я хочу изменить значение заказа, мне нужно позаботиться о сохранении существующего поиска и всех значений фильтра.

В настоящее время я делаю это, динамически генерируя строки get и скрытые входы формы в представлении и передавая их в шаблон через контекст (по одной переменной контекста для каждого из search, filter, order и каждой из form, link). А затем использую их в шаблоне следующим образом:

<form method="GET">
    {{ search_form }}

    {% autoescape off %}
        {{ preserve_q_string_in_search_form }}
    {% endautoescape %}

    <button 
        type="submit"
    >
        🔍
    </button>
</form>

или

<a
    href="?order={{ f.q_sort_desc }}&{{ preserve_q_string_in_order_href }}"
>
    DESC
</a>

Моя проблема с этим подходом заключается в том, что он одновременно довольно громоздкий (мне нужно написать логику как для всех различных запросов, так и для использования через форму и через href) и довольно хрупкий (мне нужно помнить, что нужно включить правильную переменную из контекста во все ссылки и формы).

Я также пытался справиться с этим с помощью шаблона include и нескольких пользовательских фильтров:

{% load core_filters %}

{% for getkey in request.GET %}
    {% if except_prefix and getkey|startswith:except_prefix %}
    {% else %}
        <input class="hidden" name="{{ getkey }}" value="{{ request.GET|get:getkey }}"/>
    {% endif %}
{% endfor %}
@register.filter
def get(dict: dict, key):
    """Returns value of key in dict if present, else ""."""

    return dict.get(key, "")


@register.filter
def startswith(string: str, prefix: str):
    return string.startswith(prefix)

Но обнаружил, что эта конкретная реализация довольно привередлива и слишком хакерская.

Вернуться на верх