Keeping filters in Django Admin

前端 未结 7 992
走了就别回头了
走了就别回头了 2021-02-04 20:23

What I would like to achive is:

  • I go to admin site, apply some filters to the list of objects
  • I click and object edit, edit, edit, hit \'Save\'
7条回答
  •  我在风中等你
    2021-02-04 20:39

    There's a simple hack to do this, but it's not a general solution and requires modifying every ModelAdmin which you want to support this. Maybe there is a general way to do this, but I've not spent the time to solve it on a general level.

    The first step is to write a custom FilterSpec for the filter (see Harley's post for links that will help) which saves the chosen filter value in the session (and deletes it when no longer wanted).

    # in cust_admin/filterspecs.py
    from django.contrib.admin.filterspecs import FilterSpec, ChoicesFilterSpec
    
    class MyFilterSpec(ChoicesFilterSpec):
    
        def __init__(self, f, request, params, model, model_admin):
            super(MyFilterSpec, self).__init__(f, request, params, model,
                                               model_admin)
            if self.lookup_val is not None:
                request.session[self.lookup_kwarg] = self.lookup_val
            elif self.lookup_kwarg in request.session:
                del(request.session[self.lookup_kwarg])
    
    # Register the filter with a test function which will apply it to any field
    # with a my_filter attribute equal to True
    FilterSpec.filter_specs.insert(0, (lambda f: getattr(f, 'my_filter', False),
                                   MyFilterSpec))
    

    You must import the module this is in somewhere, for example your urls.py:

    # in urls.py
    from cust_admin import filterspecs
    

    Set a property on the field you want to apply the filter to:

    # in models.py
    class MyModel(models.Model):
        my_field = Models.IntegerField(choices=MY_CHOICES)
        my_field.my_filter = True
    

    In a custom ModelAdmin class, override the change_view method, so that after the user clicks save, they are returned to the list view with their filter field value added to the URL.

    class MyModelAdmin(admin.ModelAdmin):
        def change_view(self, request, object_id, extra_context=None):
            result = super(MyModelAdmin, self).change_view(request, object_id,
                                                           extra_context)
            if '_save' in request.POST:
                if 'my_field__exact' in request.session:
                    result['Location'] = '/admin/myapp/mymodel/?my_field__exact=%s' \
                                         % request.session['my_field__exact']
            return result
    

提交回复
热议问题