Opened 10 years ago

Closed 2 years ago

#25 closed Bug (fixed)

Filtering interface on ForeignKey <select> boxes

Reported by: adrian Owned by: nobody
Component: contrib.admin Version: master
Severity: Normal Keywords: feature
Cc: rokclimb15@…, eppsilon, victorhooi Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: yes
Easy pickings: no UI/UX: yes

Description

Select boxes are a pain, and slow, to deal with when there are a lot of values to select from. (Example: datelines on news stories). There should be a generator option, use_filter_interface, available on select boxes. It would add an <input type="text"> next to the select box and allow users to filter the select box that way.

This would make data entry quicker, because folks could just paste in the dateline they want, and it'd be selected for them (assuming it's been entered as a dateline in the system).

Attachments (7)

25_patch.diff (8.5 KB) - added by cpharmston 5 years ago.
First run at it
25_screenshot.png (25.4 KB) - added by cpharmston 5 years ago.
Sample screenshot
25_patch.2.diff (8.9 KB) - added by cpharmston 5 years ago.
First run at it
select_filter.diff (12.5 KB) - added by sebleier@… 4 years ago.
I modified the previous patch and made it more efficient. Still needs to be tested in browsers other than FF and Chrome.
select_filter.2.diff (12.1 KB) - added by sebleier 4 years ago.
fixed a bug. Development can be found at https://github.com/sebleier/django/tree/feature/select-filter
select_filter.3.diff (12.1 KB) - added by sebleier 4 years ago.
fixed a bug. Development can be found at https://github.com/sebleier/django/tree/feature/select-filter
select_filter_for_Django_1_4.diff (8.4 KB) - added by jimallman <jim@…> 4 years ago.
Attempted migration to Django 1.4 (un-tested! and possibly not useful :)

Download all attachments as: .zip

Change History (42)

comment:1 Changed 9 years ago by jacob

  • milestone set to Version 1.1

comment:2 Changed 9 years ago by adrian

  • priority changed from normal to low

comment:3 Changed 9 years ago by adrian

  • Type changed from defect to enhancement

comment:4 Changed 9 years ago by anonymous

Milestone Version 1.1 deleted

comment:5 Changed 9 years ago by Gary Wilson <gary.wilson@…>

  • Triage Stage changed from Unreviewed to Design decision needed

Or even a javascript textbox+dropdown that filters entries as you type.

comment:6 Changed 8 years ago by jacob

  • Triage Stage changed from Design decision needed to Accepted

comment:7 Changed 7 years ago by mrts

  • milestone set to post-1.0

Marking as post-1.0 as this is not essential for 1.0.

comment:8 Changed 7 years ago by anonymous

  • milestone post-1.0 deleted

Milestone post-1.0 deleted

comment:9 Changed 5 years ago by cpharmston

  • Owner changed from nobody to cpharmston
  • Status changed from new to assigned

I'm going to give this a go at the DjangoCon sprint.

Changed 5 years ago by cpharmston

First run at it

Changed 5 years ago by cpharmston

Sample screenshot

comment:10 Changed 5 years ago by cpharmston

  • Has patch set
  • milestone set to 1.3
  • Version set to SVN

comment:11 Changed 5 years ago by cpharmston

I've got something workable. Screenshot and sample patch attached (I'll be submitting through a GitHub pull request). Some notes:

  • It's very slow in large (5000+) sets. Once my changes are applied, I will file another ticket in which I make some performance improvements. I will be porting those performance enhancements (which will change the behavior) to filter_horizontal and filter_vertical as well, for consistency.
  • I used jQuery for the new widget, per Jannis in #django-dev.
  • Tested in IE + Mac browsers.
  • Test and docs included.

If I get a thumbs-up, I'll submit a pull request on GitHub.

comment:12 Changed 5 years ago by cpharmston

  • Summary changed from Allow use_filter_interface on non-multiple select boxes to Filtering interface on ForeignKey <select> boxes

Changed 5 years ago by cpharmston

First run at it

comment:14 Changed 5 years ago by ericholscher

This looks like great work. I haven't taken a look at the code yet, but I will check it out during the sprints tomorrow. I'd like to see this get into core soon, as it looks damn useful.

comment:15 Changed 5 years ago by anonymous

  • Cc rokclimb15@… added

comment:16 Changed 5 years ago by ericholscher

Sorry I didn't comment earlier. I looked at this during the sprints, and the code looks good. However, I'm not too comfortable with my javascript abilities, so I didn't want to mark it RFC without knowing it would work across browsers & such.

comment:17 Changed 5 years ago by anonymous

  • Cc eppsilon added

comment:18 Changed 5 years ago by rasca

  • Keywords feature added

comment:19 Changed 5 years ago by victorhooi

  • Cc victorhooi added

heya,

Just thought I'd chime in that this is awesome =). Can't wait for this to hit trunk - hopefully it'll be soon...haha...any word on that?

Cheers,
Victor

comment:20 Changed 5 years ago by lukeplant

  • Patch needs improvement set

Victor:

It won't hit in it's current state. The patch needs a fair amount of cleaning up:

  • it doesn't apply to trunk (tests have recently been migrated to unittests)
  • it hard codes a path to '/media'
  • documentation needs to be wrapped to 80 chars

Plus we definitely need some more info about compatibility with different browsers - what versions of Firefox, Internet Explorer, Safari, Chrome and Opera does it work on? From the look of the patch, and having implemented similar things before, the use of jQuery should prevent a lot of problems, but it is very easy for this kind of thing to break in some browsers, or be unusable slow etc.

cpharmston: I'm not sure what kind of thumbs up you are looking for. Since the ticket already exists, it will be easiest just to keep an updated ticket here. Once it is ready, any committer will then be able to commit.

comment:21 Changed 5 years ago by lukeplant

Another thing - I personally would drop the 'Available' header - that makes sense for the m2m selects where you have 'Available' and 'Selected', but here it just seems to add vertical space.

comment:22 Changed 5 years ago by lrekucki

This is painfully slow for me right now. I tested this on Chrome 9.x with 2000 objects named "user". After typing in "user" in the filter it took about 3-5 seconds to refresh (on a quite fast machine). Most of the time is spent on re-creating the <option> elements one-by-one. Creating all the HTML in one shot could improve this. Not creating elements again would be probably even better (i.e. keep the option elements in the cache).

comment:23 Changed 5 years ago by victorhooi

heya,

Hmm, that's strange - the Github repository seems to 404 for me. And the cpharmston's user page doesn't exist?

https://github.com/cpharmston/

According to http://status.github.com/, Github is up and fine.

cpharmston - did you change your Github username or something?

Also, I'm curious how people think this compares to the from django-extensions:

http://code.google.com/p/django-command-extensions/

Screenshot:

http://www.flickr.com/photos/msgre/3524424961/

To be honest, I like the solution from cpharmston better, with the select box and search filter. Seems much more usable/intuitive, and also fits better with the rest of the Django admin.

Cheers,
Victor

comment:24 Changed 5 years ago by ubernostrum

  • milestone 1.3 deleted

1.3 is feature-frozen now.

comment:25 Changed 5 years ago by victorhooi

heya,

Is there any word on this patch, or anybody willing to adopt it?

From a usability POV, I think a patch like this is incredibly useful in the Django admin, particularly when the number of FK's grow large (which they invariably do).

Just like the filter_horizontal select widget, it definitely adds a lot of polish.

Anyhow, I just tried cpharmstron's patch against trunk, when I attempt to use it on an Add form I get:

'str' object has no attribute 'copy'

The full stacktrace:

Environment:


Request Method: GET
Request URL: http://nextgen.victorhooi.com/admin/conferences/attendance/add/

Django Version: 1.3 beta 1 SVN-15400
Python Version: 2.6.6
Installed Applications:
['django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.admin',
 'allocations',
 'conferences',
 'facilities',
 'nextgensite',
 'people',
 'django_extensions',
 'reversion',
 'south',
 'debug_toolbar']
Installed Middleware:
('django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'debug_toolbar.middleware.DebugToolbarMiddleware')


Traceback:
File "/sites/.virtualenvs/colloquium/src/django/django/core/handlers/base.py" in get_response
  111.                         response = callback(request, *callback_args, **callback_kwargs)
File "/sites/.virtualenvs/colloquium/src/django/django/contrib/admin/options.py" in wrapper
  312.                 return self.admin_site.admin_view(view)(*args, **kwargs)
File "/sites/.virtualenvs/colloquium/src/django/django/utils/decorators.py" in _wrapped_view
  93.                     response = view_func(request, *args, **kwargs)
File "/sites/.virtualenvs/colloquium/src/django/django/views/decorators/cache.py" in _wrapped_view_func
  79.         response = view_func(request, *args, **kwargs)
File "/sites/.virtualenvs/colloquium/src/django/django/contrib/admin/sites.py" in inner
  190.             return view(request, *args, **kwargs)
File "/sites/.virtualenvs/colloquium/src/django/django/utils/decorators.py" in _wrapper
  28.             return bound_func(*args, **kwargs)
File "/sites/.virtualenvs/colloquium/src/django/django/utils/decorators.py" in _wrapped_view
  93.                     response = view_func(request, *args, **kwargs)
File "/sites/.virtualenvs/colloquium/src/django/django/utils/decorators.py" in bound_func
  24.                 return func(self, *args2, **kwargs2)
File "/sites/.virtualenvs/colloquium/src/django/django/db/transaction.py" in inner
  282.                 res = func(*args, **kwargs)
File "/sites/.virtualenvs/colloquium/src/django/django/contrib/admin/options.py" in add_view
  852.         ModelForm = self.get_form(request)
File "/sites/.virtualenvs/colloquium/src/django/django/contrib/admin/options.py" in get_form
  437.         return modelform_factory(self.model, **defaults)
File "/sites/.virtualenvs/colloquium/src/django/django/forms/models.py" in modelform_factory
  400.     return ModelFormMetaclass(class_name, (form,), form_class_attrs)
File "/sites/.virtualenvs/colloquium/src/django/django/forms/models.py" in __new__
  206.                                       opts.exclude, opts.widgets, formfield_callback)
File "/sites/.virtualenvs/colloquium/src/django/django/forms/models.py" in fields_for_model
  164.             formfield = formfield_callback(f, **kwargs)
File "/sites/.virtualenvs/colloquium/src/django/django/utils/functional.py" in _curried
  55.         return _curried_func(*(args+moreargs), **dict(kwargs, **morekwargs))
File "/sites/.virtualenvs/colloquium/src/django/django/contrib/admin/options.py" in formfield_for_dbfield
  106.                 formfield = self.formfield_for_foreignkey(db_field, request, **kwargs)
File "/sites/.virtualenvs/colloquium/src/django/django/contrib/admin/options.py" in formfield_for_foreignkey
  167.                 db_field.verbose_name, (db_field.name in self.filter_vertical))
File "/sites/.virtualenvs/colloquium/src/django/django/forms/widgets.py" in __init__
  505.         super(Select, self).__init__(attrs)
File "/sites/.virtualenvs/colloquium/src/django/django/forms/widgets.py" in __init__
  147.             self.attrs = attrs.copy()

Exception Type: AttributeError at /admin/conferences/attendance/add/
Exception Value: 'str' object has no attribute 'copy'

Any ideas?

Cheers,
Victor

Changed 4 years ago by sebleier@…

I modified the previous patch and made it more efficient. Still needs to be tested in browsers other than FF and Chrome.

comment:26 Changed 4 years ago by sebleier

  • Owner changed from cpharmston to sebleier
  • Status changed from assigned to new

I added tests and documentation to the patch. One thing to note is that the previous patch required a fk_filter attribute on the ModelAdmin class to specify which foreignkey fields are rendered using the new filter interface. In this patch, you simply specify which foreignkey field needs the filtering interface in the ModelAdmin filter_vertical list.

Changed 4 years ago by sebleier

fixed a bug. Development can be found at https://github.com/sebleier/django/tree/feature/select-filter

Changed 4 years ago by sebleier

fixed a bug. Development can be found at https://github.com/sebleier/django/tree/feature/select-filter

comment:27 Changed 4 years ago by lrekucki

  • Severity changed from minor to Normal
  • Type changed from enhancement to New feature

comment:28 Changed 4 years ago by julien

  • UI/UX set

comment:29 Changed 4 years ago by idangazit

  • Easy pickings set

comment:30 Changed 4 years ago by victorhooi

heya,

Any update on how close this is to hitting trunk?

I mean, it's flagged "Easy pickings" by Idan *grins*, so surely it's close, right? Are there any showstopppers?

Cheers,
Victor

Btw, I also saw this:

http://harvesthq.github.com/chosen/

Chosen's a JQuery (or Prototype) plugin that basically similar combo-box support, but without the scrollable list underneath.

comment:31 Changed 4 years ago by anonymous

  • Owner changed from sebleier to anonymous
  • Status changed from new to assigned
  • Type changed from New feature to Bug

comment:32 Changed 4 years ago by jimallman <jim@…>

  • Owner changed from anonymous to jimallman
  • Status changed from assigned to new

I'm currently trying to adapt sebleier's work for Django 1.4.

Not sure who set the owner to anonymous, but I'm claiming this. (Apologies if this is bad form.)

comment:33 Changed 4 years ago by jimallman <jim@…>

  • Owner changed from jimallman to nobody

I'd like to surrender this ticket. As a relative newcomer to Django, I can't figure out whether this solution (sebleier's patch) belongs in Django 1.4, which already has raw-ID fields and select-filter widgets for this kind of user experience.

Changed 4 years ago by jimallman <jim@…>

Attempted migration to Django 1.4 (un-tested! and possibly not useful :)

comment:34 Changed 3 years ago by agiliq

  • Easy pickings unset

comment:35 Changed 2 years ago by oinopion

  • Resolution set to fixed
  • Status changed from new to closed

I think raw_id_fields is answer for this ticket and thus it should be closed as already solved.

Note: See TracTickets for help on using tickets.
Back to Top