Opened 18 years ago
Closed 20 months ago
#1873 closed New feature (fixed)
Multi-select admin filter for RelatedFields
Reported by: | Owned by: | Sarah Boyce | |
---|---|---|---|
Component: | contrib.admin | Version: | |
Severity: | Normal | Keywords: | nfa-changelist |
Cc: | msaelices@…, Luis Bruno, Andy Baker, cmawebsite@…, Sarah Boyce | Triage Stage: | Ready for checkin |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Currently, you can only select one value from a RelatedField filter in de admin interface.
This patch provides a multi-select filter, and an AND/OR switch for the values.
The patch is at
Screenshots are at
- http://www.million.nl/file/marc/django/multi-select-relatedfilterspec-and.gif
- http://www.million.nl/file/marc/django/multi-select-relatedfilterspec-or.gif
This replaces the current single-select filter, but could be used side-by-side if there was some mechanism to choose which filter to use for a particular field in the admin interface.
Todo: test what happens with multiple RelatedField filters.
Attachments (1)
Change History (39)
by , 18 years ago
Attachment: | multi-select-relatedfilterspec.2.diff added |
---|
comment:1 by , 18 years ago
comment:2 by , 18 years ago
Point 1 is also valid for 2 and 3, these changes are unrelated to the actual ticket, it is just that these snuck in while making the screenshots. I will remove the changes for contrib/auth/models.py, core/management.py and db/models/fields/related.py entirely.
Points 4 through 6 are spot-on and I'll look into that when I have a bit of time (which should be within a day or two). This patch+ticket was mainly intended to see if this idea is acceptable, and if so, if it is going in the right direction.
The thread is on django-dev as http://groups.google.com/group/django-developers/browse_thread/thread/3b209e762f09ac8f
comment:3 by , 18 years ago
Getting back to point 4, why not a COUNT(*) or COUNT(DISTINCT(*)).
The usual sql statement (simplified, leaving out the joins) looks like
select count(*) from auth_user_groups where group_id in (2,3)
This returns one row with the correct count. Note that the in(2,3) means that there are duplicates in the resultset, so a count(distinct(*)) and later a select distinct are necessary.
Now, to implement the and/or functionality, I have modified the sql to look like
select count(*) from auth_user_groups where group_id in (2,3) group by user_id having count(user_id)>= X
with X=1 for OR, and X=len(id_list) for AND.
By using a GROUP BY, I no longer get a single result, but I get a row for each user that satisfies the criteria. The count(*) for each row is now the number of matches for the group_id in (id_list).
For example, the AND case yields
user_id | count |
2 | 2 |
4 | 2 |
And the OR case
user_id | count |
3 | 1 |
2 | 2 |
4 | 2 |
Basically, the number of rows returned is once again the actual number of rows.
So, to really tackle this without fetching the rows, I could use (but I don't do that yet) a subselect, like this
select count(*) from ( select count(*) from auth_user_groups where group_id in (2,3) group by user_id having count(user_id)>= X ) as temp
That should work in most database engines (it does in Postgres), but I know older MySQL versions didn't support subselects.
comment:4 by , 18 years ago
I forgot to mention that the GROUP BY gets rid of the duplicates quite nicely :)
follow-up: 13 comment:5 by , 18 years ago
Came across this again whilst going through all the patches we have outstanding. One comment on the earlier count(*) stuff: if we ever need count(distinct(...)), not that count(distinct(*)) is not supported in SQLite. You have to do count(distint(col_name)) there. Since the primary key is unique and not NULL, it acts as a good substitute for '*'.
Also are selects in the "from" clause supported everywhere (MySQL and SQLite being ther two most likely infringers here). Haven't checked this yet, just noting it as something to resolve. Also, would we be screwing over the MS SQL Server or Firebird guys at all (Oracle does support selects in the from clause, as does PostgreSQL, so no problems with those two).
comment:6 by , 18 years ago
Cc: | added |
---|---|
Keywords: | rthml tab space editor js added |
Summary: | [patch] multi-select admin filter for RelatedFields → hi-world cup |
comment:7 by , 18 years ago
Summary: | hi-world cup → [patch] multi-select admin filter for RelatedFields |
---|
comment:8 by , 18 years ago
Cc: | removed |
---|---|
Keywords: | rthml tab space editor js removed |
Needs documentation: | set |
Patch needs improvement: | set |
Triage Stage: | Unreviewed → Design decision needed |
no more screenshots :(
comment:9 by , 18 years ago
Oops, sorry, they're back now! (hadn't realized this was still under consideration while cleaning up some stuff)
comment:10 by , 17 years ago
Triage Stage: | Design decision needed → Someday/Maybe |
---|
At some point, we'll be reworking the admin interface, and this will be one of the things we examine at that time.
comment:11 by , 17 years ago
Hi,
I am very interested in this feature. The patch (i.e. the diff file) works off a really old
version of django. Is it possible to update the patch to work with either django 0.96
or trunk code base? I tried to manually update the files, but query.py has changed significantly.
Thanks,
comment:12 by , 17 years ago
Keywords: | nfa-changelist added |
---|
comment:14 by , 16 years ago
Cc: | added |
---|
comment:16 by , 14 years ago
Owner: | changed from | to
---|
Sorry for putting this on your plate, but I think this ticket has slipped through the gaps; mind keeping an eye on it, or putting the ticket on the right guy's plate?
comment:17 by , 14 years ago
Owner: | changed from | to
---|
Don't assign tickets to other people. If you want someone to take a look at it, raise the issue on Django-dev, and see who takes the bait.
comment:18 by , 14 years ago
Severity: | normal → Normal |
---|---|
Summary: | [patch] multi-select admin filter for RelatedFields → Multi-select admin filter for RelatedFields |
Type: | enhancement → New feature |
comment:19 by , 13 years ago
UI/UX: | set |
---|
comment:23 by , 12 years ago
Cc: | added |
---|
comment:24 by , 12 years ago
Triage Stage: | Someday/Maybe → Accepted |
---|
comment:25 by , 10 years ago
Cc: | added |
---|
comment:26 by , 8 years ago
I finally thought of a possible way to do this:
Use urls like ?fieldname__in=4&fieldname__in=3
We'd need to support that both in the front end (generating those urls), and in the backend (handling repeated parameters and making sure they become lists).
I recommend only supporting the OR case (or at least starting with that). It's the expected user experience on the web, and I think it would be the most useful. (AND would only be useful in some cases for many to many's.)
comment:27 by , 8 years ago
Today I learned: Django admin already handles ?somefield__in=6,8,10
as you would hope, there's just no UI for it.
comment:28 by , 5 years ago
Duplicates, looking for filters submitting multiple values in #31338 and #29121.
For a query string like ?key=val1&key=val2&key=val3
, `ChangeList.__init__()` drops all but the last value:
self.params = dict(request.GET.items())
Even if we didn't ship filters using this, accepting multiple params would let users implement such filters themselves.
comment:29 by , 21 months ago
Cc: | added |
---|
comment:30 by , 20 months ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:31 by , 20 months ago
Needs documentation: | unset |
---|---|
Patch needs improvement: | unset |
UI/UX: | unset |
comment:32 by , 20 months ago
Patch needs improvement: | set |
---|
comment:33 by , 20 months ago
Patch needs improvement: | unset |
---|
comment:35 by , 20 months ago
Triage Stage: | Accepted → Ready for checkin |
---|
A couple of thoughts from reading through this patch (I have not tested it very thorougly yet):
__repr__()
method shoudl really be a__str__()
(since it is returning a human-readable version). The problem is that it now does not tell you what the class is, so in general it is less useful. You could create a__str__
method and use that in the place where you want it (in management.py)some_string.split(LISTVALUE_SEPARATOR)
. Isn't this going to fail badly if some of the values are strings contain commas? Or can things only be numeric ids at this point (which does not seem right, since non-numeric primary keys are permitted in Django)? Normally you need to split on commas and then work out how they would be escaped and rejoin if the tail of one fragment is the escape character(s). The escaping character can vary slightly between databases, too, from memory. Need to check how Django is doing this generically so that we can do it in a portable fashion.Anyway, nice work. The code looks like the right idea to me. Not sure if I'll use it myself, but some people might find it useful. I have no idea if the maintainers want to accept this idea or not (might be a good idea to get an indication on django-developers before going too much further in case it's a flop).
I'd be interested in knowing if you are trying to add a generic 'grouping' section to
QuerySet.extra()
, because we should then find out if Adrian et al want to add it and get it completely general, if so.