[Fixed]-How to get filtered queryset in django admin?

16👍

New version of Django admin use custom objects for ChangeList view with custom get_queryset method.

As you can see in Django source:

def changelist_view(self, request, extra_context=None):
    ...
    ChangeList = self.get_changelist(request)

    cl = ChangeList(request, self.model, list_display,
        list_display_links, list_filter, self.date_hierarchy,
        search_fields, list_select_related, self.list_per_page,
            self.list_max_show_all, self.list_editable, self)

    # Actions with no confirmation
    if (actions and request.method == 'POST' and
            'index' in request.POST and '_save' not in request.POST):
        if selected:
            response = self.response_action(request, queryset=cl.get_queryset(request))
    ...

You must override self.get_changelist(request) and return your custom ChangeList with overridden get_queryset.

ModelAdmin.get_changelist:

def get_changelist(self, request, **kwargs):
    """
    Returns the ChangeList class for use on the changelist page.
    """
    return MyChangeList  # PUT YOU OWERRIDEN CHANGE LIST HERE

MyChangeList:

from django.contrib.admin.views.main import ChangeList

class MyChangeList(ChangeList):
    def get_queryset(...):
        # if you want change get_queryset logic or add new filters
        ...
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # if you want add some context variable which can be accessed by 
        # {{ cl.some_context_varibale }} variable
        self.some_context_varibale = self.queryset.aggregate(Avg('price'))['price__avg']
👤pahaz

4👍

You can tamper with the response returned by the original changelist_view call. For example, to add some extra template context data using the queryset after it’s filtered by the admin’s ChangeList instance:

def changelist_view(self, request, extra_context=None):
    # Obtain the original response from Django
    response = super().changelist_view(request, extra_context)

    # Extract the final queryset from the ChangeList object
    change_list = response.context_data['cl']
    queryset = change_list.queryset

    # Do stuff with the queryset
    stats = self.get_stats(queryset)

    # Inject a new key in the template context data
    response.context_data['stats'] = stats

    return response

Leave a comment