1 # Django middleware to improve the admin site experience. 2 # 3 # I hate it that whenever I use the filters in django's admin to get to a 4 # selection of objects and then edit one of them, django sends me back to the 5 # unfiltered list. This small piece of middleware makes it remember the 6 # filters. It requires the admin interface to be 'mounted' as /admin/ but that 7 # can easily be changed below. 8 # 9 # When it's cached: 10 # - Every time a filter is used on /admin/app/model/ 11 # When is it used: 12 # - When coming back from an edit page 13 # When is it cleaned: 14 # - When navigating away 15 # - When clicking on a link in the list
1 # Django middleware to improve the admin site experience.
2 #
3 # I hate it that whenever I use the filters in django's admin to get to a
4 # selection of objects and then edit one of them, django sends me back to the
5 # unfiltered list. This small piece of middleware makes it remember the
6 # filters. It requires the admin interface to be 'mounted' as /admin/ but that
7 # can easily be changed below.
8 #
9 # When it's cached:
10 # - Every time a filter is used on /admin/app/model/
11 # When is it used:
12 # - When coming back from an edit page
13 # When is it cleaned:
14 # - When navigating away
15 # - When clicking on a link in the list
16 #
17 # Copyright (c) 2009 Dennis Kaarsemaker <dennis@kaarsemaker.net>
18 # All rights reserved.
19 #
20 # Redistribution and use in source and binary forms, with or without modification,
21 # are permitted provided that the following conditions are met:
22 #
23 # 1. Redistributions of source code must retain the above copyright notice,
24 # this list of conditions and the following disclaimer.
25 #
26 # 2. Redistributions in binary form must reproduce the above copyright
27 # notice, this list of conditions and the following disclaimer in the
28 # documentation and/or other materials provided with the distribution.
29 #
30 # 3. Neither the name of Django nor the names of its contributors may be used
31 # to endorse or promote products derived from this software without
32 # specific prior written permission.
33 #
34 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
35 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
36 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
37 # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
38 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
40 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
41 # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
42 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
43 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44
45 from django.core.cache import cache
46 from django.http import HttpResponseRedirect
47
48 class FilterCacheMiddleware(object):
49
50 def process_request(self, request):
51 """If needed, use cached query parameters"""
52 # Use cached query parameters
53 if request.startswith('/admin/') and request.path.count('/') == 4:
54 # When seeing things in the cache with False as use_me, someone clicked a link
55 ce = cache.get('filtercache:' + request.user.username)
56 if ce and (ce[2] == False):
57 cache.delete('filtercache:' + request.user.username)
58 # If there are still things in the cache, use them
59 elif ce and (ce[0] == request.path):
60 cache.delete('filtercache:' + request.user.username)
61 return HttpResponseRedirect('./?' + ce[1])
62
63 def process_response(self, request, response):
64 """Cache query parameters or clean cache"""
65
66 # Don't care about errors
67 if response.status_code != 200:
68 return response
69
70 # No action on non-admin pages
71 if not request.path.startswith('/admin/') or not request.path.count('/') >= 4:
72 return response
73 # On an edit page, set the use_me field to True
74 ce = cache.get('filtercache:' + request.user.username)
75 if ce and (request.path.count('/') == 5) and request.path.startswith(ce[0]):
76 ce[2] = True
77 cache.set('filtercache:' + request.user.username, ce, 300)
78 # Cache if on a list page and params given
79 elif request.path.count('/') == 4 and request.GET.items():
80 cache.set('filtercache:' + request.user.username, [request.path, request.META['QUERY_STRING'], False], 300)
81 # Clean up on other pages
82 elif ce:
83 cache.delete('filtercache:' + request.user.username)
84
85 return response
Show all