Keeping filters in Django Admin

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'
  • Site takes me to the list of objects... unfiltered. I'd like to have the filter from step 1 remembered and applied.

Is there an easy way to do it?


Asked by: Wilson764 | Posted: 24-09-2021






Answer 1

Unfortunately there's no easy way to do this. The filtering does not seem to be saved in any session variable.

Clicking back twice is the normal method, but it can be unweildy and annoying if you've just changed an object so that it should no longer be shown using your filter.

If it's just a one-off, click back twice or go through the filtering again, it's the easiest way.

If you're going to be filtering more often, or you just want to learn about hacking the admin (which is pretty open and easy), you'll want to write a FilterSpec.

Have a look here and here for examples of people writing their own.

A really, really terrible way to do this would be to edit the admin interface so that after you click "Save", you are redirected to you filtered URL. I wouldn't recommend this at all, but it's an option.

Another fairly simple way to do this would be to write a generic view to show your filtered objects, then use Django forms to edit the items from there. I'd have a look at this, you'll be stunned just how little code you have to write to get a simple view/edit page going.

Answered by: Agata939 | Posted: 25-10-2021



Answer 2

Click 2 times "Back"?

Answered by: Maddie116 | Posted: 25-10-2021



Answer 3

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

Answered by: Thomas188 | Posted: 25-10-2021



Answer 4

Another way to do this is to embed the filter in the queryset.

You can dynamically create a proxy model with a manager that filters the way you want, then call admin.site.register() to create a new model admin. All the links would then be relative to this view.

Answered by: Walter975 | Posted: 25-10-2021



Answer 5

In my opinion its better to override methods from ModelAdmin changelist_view and change_view:

Like so:

class FakturaAdmin(admin.ModelAdmin):

[...]

def changelist_view(self, request, extra_context=None):
    result = super(FakturaAdmin, self).changelist_view(request, extra_context=None)
    request.session['qdict'] = request.GET
    return result

def change_view(self, request, object_id, extra_context=None):
    result = super(FakturaAdmin, self).change_view(request, object_id, extra_context)
    try:
        result['location'] = result['location']+"?"+request.session['qdict'].urlencode()
    except:
        pass
    return result

As you wish, after save object you go back to list of objects with active filters.

Answered by: Kimberly226 | Posted: 25-10-2021



Answer 6

There is a change request at the Django project asking for exactly this functionality.

All it's waiting for to be checked in is some tests and documentation. You could write those, and help the whole project, or you could just take the proposed patch (near the bottom of the page) and try it out.

https://code.djangoproject.com/ticket/6903

Answered by: Maya314 | Posted: 25-10-2021



Answer 7

This feature has been added to Django as part of the 1.6 release and is enabled now by default. It is described in the release notes:

ModelAdmin now preserves filters on the list view after creating, editing or deleting an object. It’s possible to restore the previous behavior of clearing filters by setting the preserve_filters attribute to False.

Answered by: Luke446 | Posted: 25-10-2021



Similar questions

python - Keeping track of changes since the last save in django models

A couple of times I've run into a situation, when at save time I need to know which model fields are going to be updated and act accordingly. The most obvious solution to this is to take the primary key field and retrieve a copy of the model from the database: class MyModel(models.Model): def save(self, force_insert=False, force_update=False, using=None): if self.id is not None: ...


python - Keeping track of changes - Django

I have various models of which I would like to keep track and collect statistical data. The problem is how to store the changes throughout time. I thought of various alternative: Storing a log in a TextField, open it and update it every time the model is saved. Alternatively pickle a list and store it in a TextField. Save logs on hard drive. What are your...


Keeping track of data types in Python

So I hope this is a valid question... I've recently (today actually) decided to learn how a scripting language, so I chose Python. While glancing over code, I felt overwhelmed, and I soon realized that the reason was that I didn't know what data type conversions and stuff were going on. My question is: Is there any convention of keeping track of what the data type is? I come from more of a C background, s...


python - Keeping a pipe to a process open

I have an app that reads in stuff from stdin and returns, after a newline, results to stdout A simple (stupid) example: $ app Expand[(x+1)^2]<CR> x^2 + 2*x + 1 100 - 4<CR> 96 Opening and closing the app requires a lot of initialization and clean-up (its an interface to a Computer Algebra System), so I want to keep this...


Python - Keeping some HTML tags with lxml Xpath feature

I am writing some HTML parsers using LXML Xpath feature. It seems to be working fine, but I have one main problem. When parsing all the HTML <p> tags, there are words that use the tags <b>, <i> and etc. I need to keep those tags. When parsing the HTML, for example; <div class="ArticleDetail"> <p>Hello world, this is a ...


python - Keeping the text size the same when zooming in and out

I have created svg file with line elements, and middle point of every line represents coordinate for line's name (svg text element). What is the best way to keep the size of those text elements when zooming in and out, but their place needs to be always at the middle of the lines? In my python GUI, I zoom svg like this: def wheelEvent(self, event): factor = 1 + 0.1 * event.delta() / 120.0 s...


Python - keeping Tkinter window open?

Right now I am using Tkinter to prompt the user for a file. Tk().withdraw() # keep the root window from appearing file_path = askopenfilename() # show dialog box and return file path # check if extension is valid If the user selected the wrong file type, I re-prompt them with a new window. Is there a way, instead, to keep the same tkinter window open unless the file selected is va...


python - Join pandas series while keeping new indices

I have 2 pandas.Series: s -9999.00 26371 240.00 1755 138.99 2 s2 -9999.00 26371 240.00 1755 113.03 6 100.00 4 I have tried concat: -9999.00 26371 240.00 1755 138.99 2 -9999.00 26371 240.00 1747 113.03 6 100.00 4 and s+s2: -9999.00 52742 100.00 ...


python - Keeping track of tiles in a* search

I am having a hard time keeping track of the tiles generated by getAdjacentTiles(..). I have identified the performance issue of my A* implementation below is that I do not keep track of the tiles that have seen before, every call to getAdjacentTiles returns new tiles (Node's) and not any of the tiles in openSet or closedSet. I decided to use a list of Node o...


Keeping track of tree node's parent in Python

I have a tree of numbers. Each node can have a left and a right child node. Numbers can't repeat but they can be anywhere on the tree. I need to search for a number on the tree and then print it's pathway to the root of the tree. I can't figure a way to make a node keep track of who is it's parent so I could print them back to the root. How could I accomplish this? Code as follows: # The Tre...






Still can't find your answer? Check out these communities...



PySlackers | Full Stack Python | NHS Python | Pythonist Cafe | Hacker Earth | Discord Python



top