Как лучше всего сохранять 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)
Но обнаружил, что эта конкретная реализация довольно привередлива и слишком хакерская.