Add a new selector for related users.
Review Request #8173 — Created May 18, 2016 and submitted
We're faced with a conundrum in the admin UI when it comes to models that have
relations to other tables which can contain tons of entries. We can either use
one of django's filter widgets, which query all rows and pre-populate the form
field completely, or we can use django's "raw ID field", which has a
comma-separated list of PKs and a pop-up window search to add items. In the
first case, when there are a very large number of users (such as on public
servers), we can actually crash the web server processes. In the second case,
it's efficient but totally unusable.This change introduces a new, custom widget, which is based on selectize. This
widget provides a list for the currently selected objects, plus a searchable
drop-down to add new items. Whenever something is selected, it gets put into a
list which shows exactly what is already selected.This has the benefits of the filter widget with some extra sauce on top
(avatars, better searching), plus it's much more efficient in its queries to
the database. This is currently only implemented for relations to User (since
there's custom display and API interface code per type), but that's the big
offender anyway.
- Loaded the form with no users selected and saw an empty list.
- Loaded the form with existing users selected and saw them show up correctly.
- Clicked into the drop-down and saw it populate with the first page of results
from the API. - Started typing in a name and saw that the drop-down searched for that name
using the API. - Searched for a name which was already in the selected list and saw that it was
properly hidden from the results. - Used the keyboard to navigate to and accept a result.
- Removed items from the selected list.
- Saved the form in various states and verified that the resulting database
entries were correct.
Description | From | Last Updated |
---|---|---|
I thought we were moving away from self = this ? |
brennie | |
You can do $item = $items.eq(i) |
brennie | |
Can you add a docstring to the top of the file? Helps with the doc generation when browsing modules. |
chipx86 | |
Missing period. |
chipx86 | |
<select> should be wrapped in double backticks, so it doesn't turn into HTML when generated. |
chipx86 | |
"Gravatar" |
chipx86 | |
Djblets |
brennie | |
Blank line between these. We also should return something when value is falsy. |
chipx86 | |
If all we need to do here is override the widget, we can do so like: class MyForm(forms.ModelForm): class Meta: … |
chipx86 | |
Can we wrap each computation in parens, just so it's very clear? (Since CSS is so inconsistent about arguments.) |
chipx86 | |
Selectize is getting all kinds of maintenance done. Assuming we're matching values is scary to me. We should probably override … |
chipx86 | |
This would be a really nice thing to move into Djblets. Maybe for 3.0? |
chipx86 | |
Can this be one line, like with <select>? |
chipx86 | |
Let's put <input> in double backticks, so it's not rendered as HTML. |
chipx86 | |
Can we use events: {...} for this? |
chipx86 | |
The options should all be indented one more level. |
chipx86 | |
Double backticks. |
chipx86 | |
Double backticks. |
chipx86 | |
We should use localeCompare for string sorting, to handle rules in other languages. |
chipx86 | |
Formatting's a bit strange, because of the lengthy name. Could we maybe do the calculation outside of the conditional, and … |
chipx86 | |
Might as well include the parameter, even if it's unused. That'll at least ensure it'll be shown in the function … |
chipx86 | |
compressed_js should be indented one. |
chipx86 | |
It was already like this before, but compressed_js should be indented one. |
chipx86 | |
Instead of defining one of these inline every time we need it, can we make a proper subclass as a … |
chipx86 | |
Missing period. |
brennie | |
Can we say the version? |
chipx86 | |
Classes before tags. |
brennie | |
Classes before tags. |
brennie | |
Classes before tags. |
brennie | |
Can we list the default? |
chipx86 | |
We should probably use |escapejs here. |
brennie | |
and here. |
brennie |
-
NB: Since I made the video, I've made the field a little wider to accomodate longer real/usernames without wrapping
- Commit:
-
0e6fde1d83fe33b82b2ddb8a9ce2e0ddd91c27f39e86bc117cb1181a01b42397520ea6da1f855cff
- Diff:
-
Revision 2 (+551 -27)
-
Tool: Pyflakes Processed Files: reviewboard/staticbundles.py reviewboard/reviews/forms.py reviewboard/admin/form_widgets.py reviewboard/reviews/admin.py reviewboard/scmtools/forms.py Ignored Files: reviewboard/templates/admin/dashboard.html reviewboard/static/rb/css/pages/admin.less reviewboard/templates/admin/base_site.html reviewboard/static/rb/js/admin/views/relatedObjectSelectorView.js reviewboard/templates/admin/related_user_widget.html Tool: PEP8 Style Checker Processed Files: reviewboard/staticbundles.py reviewboard/reviews/forms.py reviewboard/admin/form_widgets.py reviewboard/reviews/admin.py reviewboard/scmtools/forms.py Ignored Files: reviewboard/templates/admin/dashboard.html reviewboard/static/rb/css/pages/admin.less reviewboard/templates/admin/base_site.html reviewboard/static/rb/js/admin/views/relatedObjectSelectorView.js reviewboard/templates/admin/related_user_widget.html
-
-
Can you add a docstring to the top of the file? Helps with the doc generation when browsing modules.
-
-
-
-
If all we need to do here is override the widget, we can do so like:
class MyForm(forms.ModelForm): class Meta: widgets = { 'people': RelatedUserWidget(), ... }
etc.
Same elsewhere.
-
Can we wrap each computation in parens, just so it's very clear? (Since CSS is so inconsistent about arguments.)
-
Selectize is getting all kinds of maintenance done. Assuming we're matching values is scary to me. We should probably override both Selectize and this, to be absolutely sure.
-
-
-
-
-
-
-
-
-
Might as well include the parameter, even if it's unused. That'll at least ensure it'll be shown in the function signature of any docs.
-
-
-
Instead of defining one of these inline every time we need it, can we make a proper subclass as a JavaScript file?
- Commit:
-
9e86bc117cb1181a01b42397520ea6da1f855cffc729f0d02fc68ed1b9bf444de2e2e4502d988709
- Diff:
-
Revision 3 (+601 -27)
-
Tool: Pyflakes Processed Files: reviewboard/staticbundles.py reviewboard/reviews/forms.py reviewboard/admin/form_widgets.py reviewboard/reviews/admin.py reviewboard/scmtools/forms.py Ignored Files: reviewboard/static/rb/js/admin/views/relatedUserSelectorView.js reviewboard/static/rb/js/admin/views/relatedObjectSelectorView.js reviewboard/static/lib/js/README.selectize reviewboard/templates/admin/dashboard.html reviewboard/templates/admin/base_site.html reviewboard/templates/admin/related_user_widget.html reviewboard/static/rb/css/pages/admin.less Tool: PEP8 Style Checker Processed Files: reviewboard/staticbundles.py reviewboard/reviews/forms.py reviewboard/admin/form_widgets.py reviewboard/reviews/admin.py reviewboard/scmtools/forms.py Ignored Files: reviewboard/static/rb/js/admin/views/relatedUserSelectorView.js reviewboard/static/rb/js/admin/views/relatedObjectSelectorView.js reviewboard/static/lib/js/README.selectize reviewboard/templates/admin/dashboard.html reviewboard/templates/admin/base_site.html reviewboard/templates/admin/related_user_widget.html reviewboard/static/rb/css/pages/admin.less
- Change Summary:
-
Optimistically use
localeCompare
- Commit:
-
c729f0d02fc68ed1b9bf444de2e2e4502d9887098062aa716c23ca745caf0dcc8d5d9642a1d24e2c
- Diff:
-
Revision 4 (+629 -27)
-
Tool: PEP8 Style Checker Processed Files: reviewboard/staticbundles.py reviewboard/reviews/forms.py reviewboard/admin/form_widgets.py reviewboard/reviews/admin.py reviewboard/scmtools/forms.py Ignored Files: reviewboard/static/rb/js/admin/views/relatedUserSelectorView.js reviewboard/static/rb/js/admin/views/relatedObjectSelectorView.js reviewboard/static/lib/js/README.selectize reviewboard/templates/admin/dashboard.html reviewboard/templates/admin/base_site.html reviewboard/templates/admin/related_user_widget.html reviewboard/static/rb/css/pages/admin.less Tool: Pyflakes Processed Files: reviewboard/staticbundles.py reviewboard/reviews/forms.py reviewboard/admin/form_widgets.py reviewboard/reviews/admin.py reviewboard/scmtools/forms.py Ignored Files: reviewboard/static/rb/js/admin/views/relatedUserSelectorView.js reviewboard/static/rb/js/admin/views/relatedObjectSelectorView.js reviewboard/static/lib/js/README.selectize reviewboard/templates/admin/dashboard.html reviewboard/templates/admin/base_site.html reviewboard/templates/admin/related_user_widget.html reviewboard/static/rb/css/pages/admin.less
- Change Summary:
-
Make requested changes.
- Commit:
-
8062aa716c23ca745caf0dcc8d5d9642a1d24e2c61d0cc5bc46c38636ee26f8b9f1cea8cb4c52a27
- Diff:
-
Revision 5 (+4685 -27)
-
Tool: Pyflakes Processed Files: reviewboard/staticbundles.py reviewboard/reviews/forms.py reviewboard/admin/form_widgets.py reviewboard/reviews/admin.py reviewboard/scmtools/forms.py Ignored Files: reviewboard/static/rb/js/admin/views/relatedUserSelectorView.js reviewboard/static/lib/css/selectize.default-0.12.1.css reviewboard/static/rb/js/admin/views/relatedObjectSelectorView.js reviewboard/static/lib/js/README.selectize reviewboard/static/rb/css/pages/admin.less reviewboard/templates/admin/base_site.html reviewboard/templates/admin/related_user_widget.html reviewboard/static/lib/js/selectize-0.12.1.js reviewboard/templates/admin/dashboard.html Tool: PEP8 Style Checker Processed Files: reviewboard/staticbundles.py reviewboard/reviews/forms.py reviewboard/admin/form_widgets.py reviewboard/reviews/admin.py reviewboard/scmtools/forms.py Ignored Files: reviewboard/static/rb/js/admin/views/relatedUserSelectorView.js reviewboard/static/lib/css/selectize.default-0.12.1.css reviewboard/static/rb/js/admin/views/relatedObjectSelectorView.js reviewboard/static/lib/js/README.selectize reviewboard/static/rb/css/pages/admin.less reviewboard/templates/admin/base_site.html reviewboard/templates/admin/related_user_widget.html reviewboard/static/lib/js/selectize-0.12.1.js reviewboard/templates/admin/dashboard.html