* easy: => 0
* stage: Design decision needed => Accepted
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:40>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* needs_docs: 0 => 1
* needs_tests: 0 => 1
Comment:
Latest patch needs tests and probably brief docs note on the behavior, not
sure if tests from earlier patch apply but they make a good starting
place.
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:41>
Comment (by julien):
#3777 was closed as a duplicate. It contains extensive discussions on this
topic.
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:42>
* cc: riccardo.magliocchetti@… (added)
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:43>
* cc: michelts@… (added)
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:44>
* cc: odin.omdal@… (added)
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:45>
* cc: gonz (removed)
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:46>
* cc: danny.adair@… (added)
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:47>
Comment (by revolunet):
Any update on @graveyboat patch ?
Does it work as expected ?
What happens when user click "save and continue" ? The referer is gone so
we may need to keep the initial one from POST if specified ?
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:48>
Comment (by richard@…):
An alternative approach for saving and restoring the filters after
editing a model:
http://djangosnippets.org/snippets/2849/
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:49>
* cc: revolunet (added)
* needs_better_patch: 0 => 1
* easy: 0 => 1
Comment:
Hi
This "bug" is quite annoying for my customers :) (lazy dudes)
I compiled as much info as possible on this thread and started a new patch
with current propositions.
I used the _return_to URL parameter approach to pass the base change list
url along in the different views and redirect accordingly
(change/add/delete/history...).
Works nicely.
I updated some regressiontests that matched a fixed url to support an
optional trailing querystring with a assertRegexpMatches.
As i'm not a TDD expert i'd appreciate recommandations on how to make it
better and which tests i should add to validate this feature.
Any comment appreciated.
Patched branch here : https://github.com/revolunet/django/compare/bug-6903
(add .patch to the url for the patch)
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:50>
* keywords: => admin
* needs_tests: 1 => 0
Comment:
I just added a full selenium test that covers the whole scenario : filter,
edit, add, addanother, continue, history, delete...
please review :)
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:51>
Comment (by akaariai):
Two comments:
1. Is there possibility of malicious use of the RETURN_GET_PARAM, that
is you could send a link of edit_something?_return_to=evil.com
2. There is some repeating of this:
{{{
if RETURN_GET_PARAM in request.GET:
url += '?%s=%s' % (RETURN_GET_PARAM,
urlquote(request.GET.get(RETURN_GET_PARAM, '')))
}}}
seems like a little helper method could make this a little more DRY.
This is just after quick skimming, no full review done.
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:52>
Comment (by revolunet):
Adressed the two issues in a new path improvements.
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:53>
Comment (by akaariai):
I added some comments to the compare view.
For the committer of this: I am not sure if the check that the return url
must start with '/' is the right one - so this check should be verified.
(Not saying it is the wrong one either - just want to make sure this will
be double checked).
I don't think I am the right committer for this, there are committers who
know this area of Django way better than me.
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:54>
Comment (by revolunet):
Due to popular request, i finally replaced the wonderful Selenium Test
with a more standard but more quick standard TestCase. (Duration is now
1.5s versus 5s with selenium)
Any others improvements advises here ?
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:55>
* easy: 1 => 0
Comment:
Thanks for all your work on the patch so far. I think that overall the
redirections work pretty well and quite intuitively.
However, I have some concerns regarding the continuous passing-around of
the querystring parameter. Firstly, it makes the implementation more
complex as we have to check for the existence of that parameter in many
places in the code — not only does this already require a lot of new code
in the current implementation, but as we continue to extend the admin's
functionality we'll have to continue to add lots of similar code just to
ensure that this querystring parameter is correctly taken care of.
Secondly, it makes the admin urls really long and ugly — this would have a
negative impact on the user experience. Thirdly, while introducing a
querystring parameter could be seen as a nice new feature, I fear it might
be abused and exploited for too many different things outside of the
original use case.
Besides, while I agree that using explicit urls is generally a good thing
on the web, in this case I think it is purely a convenient way of
navigating the site by one given user. How the changelist was previously
filtered by user A before accessing an object is most likely not going to
be interesting or useful to any other user B. So there's no reason for
user A to provide this information when sharing an object's url with user
B.
For all these reasons, my strong preference would be to use sessions
instead of a querystring parameter. 1) Each time the changelist is
rendered: if any filters are used then store them in the session otherwise
clear the session; and 2) When comes the time to redirect to the
changelist (i.e. after an object gets saved), then use the filters saved
in the session, if any.
The session would be used to save the state of the changelist as it was
last seen by the user. If the user opens multiple browser tabs for the
changelist and operates multiple different filterings in each tab, then
only the last filtering that is operated would be kept in the session.
Also, to be clear, we do not want to have situations where the
changelist's filtering doesn't match what is displayed in the browser's
address bar. So the filtering saved in the session should only be
retrieved when there is a redirection, and the redirection's url should
include all the corresponding querystring parameters. This means for
example that if you directly click on model name on the admin index page,
then you should be sent to the changelist's "clean" url (i.e. without any
querystring parameters) and the session's filtering should be cleared.
I hope this is clear. While I personally would prefer using sessions, I
don't want my opinion to be too authoritative at this point and I'm happy
to hear counter-opinions from other core-devs and any one else.
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:56>
Comment (by hejsan):
Why not cookies?
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:57>
Comment (by Velmont):
Here's someone else. It makes much sense not to clutter the urls with
something that should be an implementation detail. Rather than doing it as
a session, it might also be possible just to do it client-side with
localStorage. If I'd hacked a quickfix patch myself, I'd probably do that.
Minimal changes. But it wouldn't fix the problem when not using javascript
ofc.
I'll take the patch as it is now into a membership management system,
hopefully I won't have to do it for next release. The workflow is hampered
without it :-)
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:58>
Comment (by aaugustin):
Replying to [comment:57 hejsan]:
> Why not cookies?
cookies == session
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:59>
Comment (by jarrow):
To cite my four years younger self ;)
> I proposed to use the session to store the filters so that you don't
pass your filters and search queries around whenever you pass the URL of
an edit form to someone else. So I would use a hash of the data and use it
as a key in the session. This key would then be passed around instead of
the info.
So yes, I'm all for using the session, '''but''' I think it would be great
to still have a querystring parameter that holds a hash/key of the data
that it is in the session (i.e. filter settings). This way one could work
with multiple browser windows and it would still work as expected.
Great to see this is moving again! Go, Django! :)
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:60>
Comment (by revolunet):
Hi guys, thanks for reviewing/commenting again... this has definitely to
be fixed.
After have read all the comments, i first went with the URL solution.
Works well but makes urls a little ugly, true. if this is a problem for
most of you, we can go with the session.
The session is another approach that could also work well and i can
rewrite my patch and tests to make this happen :)
The only little issue is multi-windows but this could be resolved in a 2nd
pass?
I understand and agree with the fact that this session filters is just
one-time use and should not affect the direct links to the change list.
Waiting for your approval to kill this one...
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:61>
Comment (by revolunet):
Hi :)
So here's my session based patch :
https://github.com/revolunet/django/compare/bug-6903-2
Its much more simpler than the querystring based approach :
- records the current changelist querystring in an
`admin_[APP]_[MODEL]_filters` session variable
- if any, redirect with that querystring on add/change/delete object
I added some standard unittests
comments ?
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:62>
Comment (by julien):
Thanks revolunet for updating the patch. I've started reviewing it. I'll
try to provide some detailed feedback soon.
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:63>
Comment (by julien):
Ok, so the review took a bit longer than anticipated as I realized we
first needed to clean up the `ModelAdmin` API a little in #19505.
This allows a much more succinct and cleaner approach as in the patch
above.
Tests are still needed. The tests from the previous patch could probably
be reused. However, they could be simplified a bit by testing a model
simpler than `auth.User`.
As always, feedback is appreciated. Thanks!
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:64>
* cc: andybak (added)
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:65>
Comment (by revolunet):
any news on this ?
needs more improvments ?
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:66>
Comment (by julien):
I think the latest patch above looks good. Only tests should be added and
slightly improved as noted in my previous comment. I'll try to get to that
soon if no one beats me up to it.
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:67>
Comment (by gabbork):
hi, will you include this new feature in next 1.5 django release?
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:68>
Comment (by julien):
Replying to [comment:68 gabbork]:
> hi, will you include this new feature in next 1.5 django release?
1.5 has been in feature-freeze mode since the first release candidate came
out some weeks ago. I'm really hoping to have it included in 1.6 though.
I'm planning to wrap up the patch this weekend during the worldwide
sprint, and then I'll be seeking feedback from users to make sure we get
the user experience right.
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:69>
Comment (by julien):
Ok, so I have wrapped up the implementation and tests. There is just one
minor test failure:
{{{
======================================================================
FAIL: test_changelist_view_count_queries
(regressiontests.admin_views.tests.AdminCustomQuerysetTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/django/tests/regressiontests/admin_views/tests.py", line 2550, in
test_changelist_view_count_queries
self.assertEqual(resp.context['selection_note_all'], 'All 2 selected')
File "/django/django/test/testcases.py", line 195, in __exit__
executed, self.num
AssertionError: 6 != 4 : 6 queries executed, 4 expected
}}}
I haven't looked into this yet but it's most likely because the session
lookups require extra database queries (which is normal).
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:70>
Comment (by loic84):
I'd like to voice my concern regarding this approach. We typically deal
with the admin using multiple tabs and with this patch the redirect
becomes rather unpredictable.
I'd love a solution for persistent `ChangeList` filters since the current
behavior forces us to set all our filters repeatedly but at least what is
happening is obvious. It's extremely confusing to land on an empty
`ChangeList` upon saving because in parallel you checked something in a
different tab and set a restrictive bunch of filters.
There ought to be a direct connection between the `ChangeList` that led to
a add/change form and the `ChangeList` it redirects to.
Maybe a hidden form field and a querystring parameter for the delete link?
Actually semantically it would even make sense that the delete link be
changed to a delete form with a submit button.
BTW, if you still plan to go ahead with the current patch, `module_name`
should be amended to `model_name`.
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:71>
* cc: kraken (added)
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:72>
Comment (by julien):
@loic84: I agree with these concerns. I'd like to avoid cluttering the
urls so a hidden field sounds like a sane approach.
This means the match needs to be reworked further. The tests should also
be extended to simulate a multi-tab use case. If someone can propose a
patch that would be great, otherwise I'll try to work on it at Pycon.
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:73>
Comment (by revolunet):
Wow. There are 12 patches in this page, made by various people, and the
desired implementation is still not defined.
This feature may not be a priority, even if more than 3 years old, but
would be cool if the core team could agree on the implementation so we can
try again and kill that one ;)
Anyone here going at djangocon.eu and interested in fixing that with me ?
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:74>
Comment (by julien):
While I like the idea of a hidden field in the change form, we still need
a way of passing the filters from the changelist to the change form when
an object is clicked in the changelist. Passing the filters via the
querystring would look a bit ugly and would kind of defeat the purpose of
using a hidden field.
Ideally, I'd like a way that doesn't clutter the urls and also satisfies
the principle of least surprise :)
Sorry I haven't had much time to think all of this through yet. Please
don't let this deter you from working on this patch. I'll continue to
provide feedback whenever needed. Thanks!
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:75>
Comment (by loic84):
@julien: when the user goes from `changelist_view` to `change_view` you
can retrieve the querystring from HTTP_REFERER.
The only time where you might need an ugly URL is for the delete link, but
I think we should POST (instead of GET) to the `delete_view` anyway, just
like we do for the delete action.
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:76>
Comment (by julien):
Using the http referer us a good idea. I've just posted a quick proof of
concept (I haven't tested this manually yet).
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:77>
Comment (by empty):
The original querystring approach has worked fine for us for years. Are we
over thinking the approach on this? I'd really like to see this get in.
It's sort of a non starter for a lot of our clients.
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:78>
* owner: => oinopion
* cc: tomek@… (added)
* status: new => assigned
Comment:
I've updated older patch by julien. It was missing passing filters to
delete view. It is still missing some `is_safe_url` checks.
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:79>
Comment (by oinopion):
I've submitted [https://github.com/django/django/pull/1264 pull request]
from previous ticket with some small corrections.
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:80>
* needs_better_patch: 1 => 0
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:81>
* needs_docs: 1 => 0
Comment:
I'm not really sure what kind of documentation this would need: Functional
details of admin are not documented. Release notes might be a good place,
but should I put it in 1.6?
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:82>
Comment (by loic84):
Somehow I missed the updates for that ticket and just saw oinopion's PR on
github.
I really like the patch, except that I would have taken this opportunity
to turn the delete link into a delete button.
1. It's more in line with the HTTP spec where GET should be free of side
effects. (We do have a confirmation page, but that's an implementation
detail.)
2. It's consistant with the `change_list` delete action, and the rest of
the `change_view` actions.
4. It avoids special casing the delete link in this patch.
5. Less importantly, it avoids an ugly URL for the delete confirmation
page.
That said, this could be changed later in a different patch/ticket but I
doubt such a minor cleanup would get much attention on its own.
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:83>
Comment (by anonymous):
Can we please not bikeshed about delete link? It does not bring us any
closer to closing this 5 years old ticket.
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:84>
* needs_better_patch: 0 => 1
Comment:
I looked further into it, I pass on the delete link as there is no easy
way to POST to the delete URL because `submit_line.html` is included
within a form, and you can't have a form within a form. Fixing it requires
a refactor too big to be within the scope of this ticket.
That said, the patch and the tests only cover the basic scenarios:
- `change_list > add_view > save`
- `change_list > change_view > save`
- `change_list > delete_view > save`
You are out of luck if you do:
- `change_list > change_view (Save and continue editing) > change_view >
save`
- `change_list > change_view (Save and add another) > add_view > save`
The reason we lose track of filters is that `_continue`, `_saveasnew` and
`_addanother` rely on `HttpResponseRedirect` so we have to use the
querystring for such cases.
At this point I agree with @empty, I'd vote to use querystring everywhere,
the URL is not that ugly and if anything, it gives some context of where
you came from. If you want to keep the pretty URLs where possible, just
append the querystring to these `HttpResponseRedirect` and allow
`_changelist_filters` to come from either POST or GET.
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:85>
Comment (by loic84):
I've tried to sum up the different options that have been used so far in
this ticket.
'''The problem:'''
We need the sticky filters to survive an arbitrarily long path made of
GET, POST, and Redirects.
'''The options:'''
The only 2 *consistent* ways of doing it are the querystring and the
session. There is a third option that involve reading the referrer and
storing information in a hidden field, but at least for redirects and html
links we need a fallback method.
There is no perfect solution:
- If we pick the querystring, we add a lot of things to the URLs.
- If we pick the session, we lose the direct link between the
`change_list` that started the chain of events and the one to which we
return. (as explained in comment:71)
- If we pick an hybrid solution, we lack consistency and we still suffer
from the defects of whatever we use as a fallback.
For the issue at hand I value predictably and reliability much more than
the aesthetic of the URL, especially for an admin site. So I'd like to
suggest using the querystring and offering an option to switch off the
behavior: `ModelAdmin.sticky_filters`. The developer gets to pick, he can
have prestine URLs or a robust preservation of changelist filters, not
both. If we go with that, we'll have to decide what's the default value of
the `sticky_filters` flag.
Proof of concept: https://github.com/loic/django/compare/ticket6903
I tested it manually and I have yet to fail it, I'll write the docs and
tests tomorrow.
Unlike previous attempts at using the querystring, it relies on a
templatetag that accounts for existing querystring parameters.
I've also left out the breadcrumbs, as I like that they point to a fresh
`change_list`, but that's debatable, I can easily add them.
Thoughts?
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:86>
* cc: charettes (added)
Comment:
I also think the querystring is the more appropriate approach, not sure
about the `sticky_filters` wording thought.
I'd say leave the breadcrumbs as they are.
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:87>
Comment (by empty):
Four years ago I started using the querystring approach to this problem
and it has worked flawlessly. I'm not sure why there's such consternation
over the query string parameters in the URL. It's actually quite useful
(for sending to a friend) and the exact same behavior you would get with
regular filtering of the change list.
I understand the desire to get the "perfect" implementation here but
sometimes "great" is the enemy of "good enough". Perhaps we can get some
resolution by going forward with the querystring approach. It's not as
though anything is lost by implementing this.
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:88>
Comment (by revolunet):
The querystring approach has the advantages of being explicit and allow to
have multi-tabs/windows in different states.
Having the breadcrumbs use the QS is optional but i thing it adds some
comfort for the user (let's get back to where i were)
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:89>
Comment (by loic84):
Alright, it seems we reached some consensus, hopefully we'll have a RFC
patch by today.
I'm not particularly attached to the `sticky_filters` wording. At first I
went with `changelist_filters` as spotted in a different patch, but then I
thought that would create confusion with the existing
`ModelAdmin.list_filter`. If we find a better name, I'll query-replace the
whole thing. Note that the user facing string (in the URL) is
`_changelist_filters`, the underscore is there as a precaution but I guess
it's unlikely people would have a model field named "changelist_filters".
For the breadcrumbs, I'm leaving it as it is and I'll see after a couple
more people have chipped in, when the patch is complete, I'll do whatever
is more popular.
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:90>
Comment (by charettes):
@loic84 FWIW model fields can't start with an underscore anyway.
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:91>
Comment (by loic84):
PR https://github.com/django/django/pull/1281
I eventually replaced "sticky" by "preserve/preserved".
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:92>
Comment (by aaugustin):
Fixed in c86a9b63984f6692d478f6f70e3c78de4ec41814.
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:93>
Comment (by revolunet):
woot ! thanks guys
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:94>
* status: assigned => closed
* resolution: => fixed
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:95>
* cc: honyczek@… (added)
Comment:
have your tried it on productional web server? It doesn't work for me at
Apache/2.2.22 (Linux/SUSE) mod_ssl/2.2.22 OpenSSL/1.0.1e mod_wsgi/3.3
Python/2.7.3
If I try run the same code on the server on Django development web server
(port 8000), filtering is preserved. If I run it on Apache and WSGI, it
doesn't work.
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:96>
Comment (by Tim Graham <timograham@…>):
In [changeset:"4339e9a92d98371a50a6fe54ab7ea0c602ecee28"]:
{{{
#!CommitTicketReference repository=""
revision="4339e9a92d98371a50a6fe54ab7ea0c602ecee28"
Fixed #21795 -- Made add_preserved_filters account for url prefixes.
Thanks to trac username honyczek for the report. Refs #6903.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:97>
Comment (by Tim Graham <timograham@…>):
In [changeset:"a5297c1ef4c4c010d1eb979177d4633beb5f9cad"]:
{{{
#!CommitTicketReference repository=""
revision="a5297c1ef4c4c010d1eb979177d4633beb5f9cad"
[1.6.x] Fixed #21795 -- Made add_preserved_filters account for url
prefixes.
Thanks to trac username honyczek for the report. Refs #6903.
Backport of 4339e9a92d from master
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:99>
Comment (by Tim Graham <timograham@…>):
In [changeset:"5268d71f18d12c362d74010210309c1cec8e8a1a"]:
{{{
#!CommitTicketReference repository=""
revision="5268d71f18d12c362d74010210309c1cec8e8a1a"
[1.7.x] Fixed #21795 -- Made add_preserved_filters account for url
prefixes.
Thanks to trac username honyczek for the report. Refs #6903.
Backport of 4339e9a92d from master
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:98>
Comment (by Mariusz Felisiak <felisiak.mariusz@…>):
In [changeset:"b142bd4a1b83b77c5c81a8cf5a80a63608f96ad4" b142bd4a]:
{{{
#!CommitTicketReference repository=""
revision="b142bd4a1b83b77c5c81a8cf5a80a63608f96ad4"
Refs #6903 -- Adjusted ModelAdmin.preserve_filters docs.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:99>
Comment (by Mariusz Felisiak <felisiak.mariusz@…>):
In [changeset:"268ba2db8e0b94359f19c3f387a2a5555f701154" 268ba2d]:
{{{
#!CommitTicketReference repository=""
revision="268ba2db8e0b94359f19c3f387a2a5555f701154"
[3.1.x] Refs #6903 -- Adjusted ModelAdmin.preserve_filters docs.
Backport of b142bd4a1b83b77c5c81a8cf5a80a63608f96ad4 from master
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:100>
Comment (by Mariusz Felisiak <felisiak.mariusz@…>):
In [changeset:"9e4f55757dcdb171c515d65a4d8e9ff5dc33a8f8" 9e4f5575]:
{{{
#!CommitTicketReference repository=""
revision="9e4f55757dcdb171c515d65a4d8e9ff5dc33a8f8"
[3.0.x] Refs #6903 -- Adjusted ModelAdmin.preserve_filters docs.
Backport of b142bd4a1b83b77c5c81a8cf5a80a63608f96ad4 from master
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/6903#comment:101>