Default filter in Django admin

前端 未结 15 1738
有刺的猬
有刺的猬 2020-11-27 10:49

How can I change the default filter choice from \'ALL\'? I have a field named as status which has three values: activate, pending and

相关标签:
15条回答
  • 2020-11-27 10:54

    Note that if instead of pre-selecting a filter value you want to always pre-filter the data before showing it in the admin, you should override the ModelAdmin.queryset() method instead.

    0 讨论(0)
  • 2020-11-27 11:00

    Took ha22109's answer above and modified to allow the selection of "All" by comparing HTTP_REFERER and PATH_INFO.

    class MyModelAdmin(admin.ModelAdmin):
    
        def changelist_view(self, request, extra_context=None):
    
            test = request.META['HTTP_REFERER'].split(request.META['PATH_INFO'])
    
            if test[-1] and not test[-1].startswith('?'):
                if not request.GET.has_key('decommissioned__exact'):
    
                    q = request.GET.copy()
                    q['decommissioned__exact'] = 'N'
                    request.GET = q
                    request.META['QUERY_STRING'] = request.GET.urlencode()
            return super(MyModelAdmin,self).changelist_view(request, extra_context=extra_context)
    
    0 讨论(0)
  • 2020-11-27 11:07

    You can simply usereturn queryset.filter() or if self.value() is None and Override method of SimpleListFilter

    from django.utils.encoding import force_text
    
    def choices(self, changelist):
        for lookup, title in self.lookup_choices:
            yield {
                'selected': force_text(self.value()) == force_text(lookup),
                'query_string': changelist.get_query_string(
                    {self.parameter_name: lookup}, []
                ),
                'display': title,
            }
    
    0 讨论(0)
  • 2020-11-27 11:08
    class MyModelAdmin(admin.ModelAdmin):   
    
        def changelist_view(self, request, extra_context=None):
    
            if not request.GET.has_key('decommissioned__exact'):
    
                q = request.GET.copy()
                q['decommissioned__exact'] = 'N'
                request.GET = q
                request.META['QUERY_STRING'] = request.GET.urlencode()
            return super(MyModelAdmin,self).changelist_view(request, extra_context=extra_context)
    
    0 讨论(0)
  • 2020-11-27 11:11

    Here is my generic solution using redirect, it just checks if there are any GET parameters, if none exist then it redirects with the default get parameter. I also have a list_filter set so it picks that up and displays the default.

    from django.shortcuts import redirect
    
    class MyModelAdmin(admin.ModelAdmin):   
    
        ...
    
        list_filter = ('status', )
    
        def changelist_view(self, request, extra_context=None):
            referrer = request.META.get('HTTP_REFERER', '')
            get_param = "status__exact=5"
            if len(request.GET) == 0 and '?' not in referrer:
                return redirect("{url}?{get_parms}".format(url=request.path, get_parms=get_param))
            return super(MyModelAdmin,self).changelist_view(request, extra_context=extra_context)
    

    The only caveat is when you do a direct get to the page with "?" present in the url, there is no HTTP_REFERER set so it will use the default parameter and redirect. This is fine for me, it works great when you click through the admin filter.

    UPDATE:

    In order to get around the caveat, I ended up writing a custom filter function which simplified the changelist_view functionality. Here is the filter:

    class MyModelStatusFilter(admin.SimpleListFilter):
        title = _('Status')
        parameter_name = 'status'
    
        def lookups(self, request, model_admin):  # Available Values / Status Codes etc..
            return (
                (8, _('All')),
                (0, _('Incomplete')),
                (5, _('Pending')),
                (6, _('Selected')),
                (7, _('Accepted')),
            )
    
        def choices(self, cl):  # Overwrite this method to prevent the default "All"
            from django.utils.encoding import force_text
            for lookup, title in self.lookup_choices:
                yield {
                    'selected': self.value() == force_text(lookup),
                    'query_string': cl.get_query_string({
                        self.parameter_name: lookup,
                    }, []),
                    'display': title,
                }
    
        def queryset(self, request, queryset):  # Run the queryset based on your lookup values
            if self.value() is None:
                return queryset.filter(status=5)
            elif int(self.value()) == 0:
                return queryset.filter(status__lte=4)
            elif int(self.value()) == 8:
                return queryset.all()
            elif int(self.value()) >= 5:
                return queryset.filter(status=self.value())
            return queryset.filter(status=5)
    

    And the changelist_view now only passes the default parameter if none are present. The idea was to get rid of the generics filters capability to view all by using no get parameters. To view all I assigned the status = 8 for that purpose.:

    class MyModelAdmin(admin.ModelAdmin):   
    
        ...
    
        list_filter = ('status', )
    
        def changelist_view(self, request, extra_context=None):
            if len(request.GET) == 0:
                get_param = "status=5"
                return redirect("{url}?{get_parms}".format(url=request.path, get_parms=get_param))
            return super(MyModelAdmin, self).changelist_view(request, extra_context=extra_context)
    
    0 讨论(0)
  • 2020-11-27 11:12
    def changelist_view( self, request, extra_context = None ):
        default_filter = False
        try:
            ref = request.META['HTTP_REFERER']
            pinfo = request.META['PATH_INFO']
            qstr = ref.split( pinfo )
    
            if len( qstr ) < 2:
                default_filter = True
        except:
            default_filter = True
    
        if default_filter:
            q = request.GET.copy()
            q['registered__exact'] = '1'
            request.GET = q
            request.META['QUERY_STRING'] = request.GET.urlencode()
    
        return super( InterestAdmin, self ).changelist_view( request, extra_context = extra_context )
    
    0 讨论(0)
提交回复
热议问题