From 0835b73d9a0d7cedabe766559288ee442e78f5f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Dlouh=C3=BD?= Date: Mon, 5 May 2025 13:06:16 +0200 Subject: [PATCH] fix #45 (Pagination does not carry filter parameters) --- django_admin_search/admin.py | 64 +++++++++++++++---- .../templates/admin/filter.html | 8 +++ .../templates/admin/pagination.html | 24 +++++++ 3 files changed, 82 insertions(+), 14 deletions(-) create mode 100644 django_admin_search/templates/admin/filter.html create mode 100644 django_admin_search/templates/admin/pagination.html diff --git a/django_admin_search/admin.py b/django_admin_search/admin.py index 2d1e8ad..659a000 100644 --- a/django_admin_search/admin.py +++ b/django_admin_search/admin.py @@ -4,6 +4,7 @@ from django.core.exceptions import ValidationError from django.db.models import Q from django.utils.translation import gettext_lazy as _ +from urllib.parse import urlencode from django_admin_search import utils @@ -29,30 +30,51 @@ def get_queryset(self, request): def changelist_view(self, request, extra_context=None): """ - Append custom form to page render + Append custom form and search parameters to page render """ extra_context = extra_context or {} + advanced_search_params = {} + if hasattr(self, 'search_form'): + original_get = request.GET.copy() + self.advanced_search_fields = {} - self.search_form_data = self.search_form(request.GET.dict()) - self.extract_advanced_search_terms(request.GET) - extra_context.update({'asf': self.search_form_data}) + self.search_form_data = self.search_form(original_get) + is_form_valid = self.search_form_data.is_valid() + self.extract_advanced_search_terms(original_get, is_form_valid) + + form_fields = self.search_form_data.fields.keys() if self.search_form_data else [] + for key, value_list in original_get.lists(): + if key in form_fields and self.advanced_search_fields.get(key): + advanced_search_params[key] = value_list + + extra_context.update({ + 'asf': self.search_form_data, + 'advanced_search_params': urlencode(advanced_search_params, doseq=True) + }) + + response = super().changelist_view(request, extra_context=extra_context) - return super().changelist_view(request, extra_context=extra_context) + if hasattr(response, 'context_data'): + response.context_data.update(extra_context) - def extract_advanced_search_terms(self, request): + return response + + def extract_advanced_search_terms(self, request_get, is_form_valid): """ - allow to extract field values from request + Extract field values from the provided GET dictionary. + Uses the populated search_form_data to identify relevant fields. """ - request._mutable = True # pylint: disable=protected-access + self.advanced_search_fields = {} - if self.search_form_data is not None: - for key in self.search_form_data.fields.keys(): - temp = request.pop(key, None) - if temp: # there is a field but it's empty so it's useless - self.advanced_search_fields[key] = temp + if self.search_form_data and is_form_valid: + for key, field in self.search_form_data.fields.items(): + cleaned_value = self.search_form_data.cleaned_data.get(key) - request._mutable = False # pylint: disable=protected-access + if cleaned_value is not None and cleaned_value != '': + value_list = request_get.getlist(key) + if any(v is not None and v != '' for v in value_list): + self.advanced_search_fields[key] = value_list def get_request_field_value(self, field): """ @@ -109,3 +131,17 @@ def advanced_search_query(self, request): query &= self.get_field_value(field, form_field, field_value, has_field_value, request) return query + + def lookup_allowed(self, lookup, value, request=None): + if hasattr(self, 'search_form') and self.search_form and hasattr(self.search_form, 'base_fields'): + for field, form_field in self.search_form.base_fields.items(): + widget_attrs = getattr(form_field.widget, 'attrs', {}) + base_lookup = widget_attrs.get('filter_field', field) + filter_method = widget_attrs.get('filter_method', '') + + generated_lookup = f"{base_lookup}{filter_method}" + + if lookup == generated_lookup: + return True + + return super().lookup_allowed(lookup, value, request) diff --git a/django_admin_search/templates/admin/filter.html b/django_admin_search/templates/admin/filter.html new file mode 100644 index 0000000..2c4e4cf --- /dev/null +++ b/django_admin_search/templates/admin/filter.html @@ -0,0 +1,8 @@ +{% load i18n %} +

{% blocktranslate with filter_title=title %} By {{ filter_title }} {% endblocktranslate %}

+ \ No newline at end of file diff --git a/django_admin_search/templates/admin/pagination.html b/django_admin_search/templates/admin/pagination.html new file mode 100644 index 0000000..32fbf4e --- /dev/null +++ b/django_admin_search/templates/admin/pagination.html @@ -0,0 +1,24 @@ +{% load admin_list %} +{% load i18n %} +
+{% if pagination_required %} + + {% if page_obj.has_previous %} + + {% endif %} + + + {% blocktranslate with page_number=page_obj.number total_pages=paginator.num_pages %} + Page {{ page_number }} of {{ total_pages }}. + {% endblocktranslate %} + + + {% if page_obj.has_next %} + + {% endif %} + +{% endif %} + +{% cl_show_full_result_count %} + +
\ No newline at end of file