Django Admin: Как установить фильтр по умолчанию, не конфликтуя с выбранными пользователем фильтрами?

Я работаю с панелью Django Admin и мне нужно установить фильтр по умолчанию для представления списка изменений модели. Когда пользователь открывает страницу списка изменений в первый раз, я хочу, чтобы она автоматически фильтровалась по определенному значению (например, status="A"). Однако, когда пользователь выбирает другой фильтр (например, status="B"), фильтр по умолчанию (status="A") не должен применяться.

Что я пробовал: Я переопределил метод changelist_view в классе ModelAdmin, чтобы проверить, присутствует ли в запросе какой-либо фильтр статуса. Если нет, я добавляю фильтр по умолчанию (status=A). Вот как выглядит мой код:

from django.contrib import admin
from django.shortcuts import redirect
from django.urls import reverse
from .models import Person  # Replace with your actual model

class PersonAdmin(admin.ModelAdmin):
    list_display = ('name', 'status')  # Adjust fields to match your model
    list_filter = ('status',)  # Adjust filters to match your model

    def get_queryset(self, request):
        # Get the original queryset without any default filtering
        qs = super().get_queryset(request)
        return qs

    def changelist_view(self, request, extra_context=None):
        # Check if any filters related to 'status' are already applied by looking at request.GET
        if 'status' not in request.GET and 'status__exact' not in request.GET:
            # Redirect to the same changelist URL with the default filter applied
            query = request.GET.copy()  # Make a mutable copy of GET parameters
            query['status'] = 'A'  # Set the default filter value for 'status' to 'A'
            
            # Redirect to the changelist URL with the correct query string
            return redirect(
                f"{reverse('admin:Human_Resource_Management_person_changelist')}?{query.urlencode()}"
            )

        # Call the original changelist_view method
        return super().changelist_view(request, extra_context=extra_context)

# Register your admin class with the associated model
admin.site.register(Person, PersonAdmin)
<

Изначально код работает: когда представление списка изменений загружается без каких-либо фильтров, по умолчанию устанавливается статус=A. Однако если пользователь выбирает другой фильтр, например status=B, то URL выглядит следующим образом: ?status=A&status__exact=B В результате оба фильтра применяются одновременно, что неправильно. Я хочу, чтобы применялся только выбранный пользователем фильтр (например, status=B) и не сохранялся фильтр по умолчанию (status=A) в URL.

Что я пробовал: Я пробовал изменять request.GET напрямую, но это вызвало ошибку AttributeError, поскольку request.GET неизменяем. Я также пробовал более сложные проверки условий, но, похоже, не могу предотвратить сохранение фильтра status=A в URL при выборе другого фильтра. Что я ищу: Я ищу решение, которое:

Применяет фильтр по умолчанию (status=A) только в том случае, если нет другого фильтра статуса. Удаляет фильтр по умолчанию, когда пользователь выбирает другой фильтр (status=B), чтобы избежать конфликтующих фильтров в URL. Любые соображения или предложения о том, как этого добиться, будут высоко оценены!

Спасибо!

Фильтр отбрасывает предыдущий фильтр с тем же именем. Но вы используете status, а не status__exact, отсюда и проблема. Вместо этого используйте status__exact:

class PersonAdmin(admin.ModelAdmin):
    # …

    def changelist_view(self, request, extra_context=None):
        if 'status' not in request.GET and 'status__exact' not in request.GET:
            # Redirect to the same changelist URL with the default filter applied
            query = request.GET.copy()  # Make a mutable copy of GET parameters
            query['status__exact'] = 'A'  # Set the default filter value for 'status' to 'A'

            # Redirect to the changelist URL with the correct query string
            return redirect(
                f"{reverse('admin:Human_Resource_Management_person_changelist')}?{query.urlencode()}"
            )

        # Call the original changelist_view method
        return super().changelist_view(request, extra_context=extra_context)
Вернуться на верх