Warning
This is still a work in progress. Some backwards incompatible changes may happen between releases.
This project is a kind of a plugin for django-selectable.
It provides widgets for use with a great JS library called select2 rather than jQuery UI.
For now there's only a basic single-valued autocomplete widget for usage on ForeignKey (or simply ModelChoiceField) fields.
install django-selectable (you can ommit the part regarding jquery-ui)
install django-selectable-select2 like so:
pip install django-selectable-select2
add selectable_select2 to INSTALLED_APPS. So it look like this:
INSTALLED_APPS = ( ... 'selectable', 'selectable_select2', ... )
add/change a setting
SELECTABLE_ESCAPED_KEYS
like this:SELECTABLE_ESCAPED_KEYS = ('label', 'value')
You can also get all the static files dependencies like this:
pip install django-staticfiles-jquery pip install django-staticfiles-select2
and add them to INSTALLED_APPS
:
INSTALLED_APPS = ( ... 'jquery', 'staticfiles_select2', ... )
define your lookup class
in your forms you can use
selectable_select2.widgets.AutoCompleteSelect2Widget
like so:from selectable_select2.widgets import AutoCompleteSelect2Widget from django import forms from myapp.models import MyModel # example model with a ForeignKey called ``myfk`` from myapp.lookups import MyModelLookup # the lookup defined in previous step class MyModelForm(forms.ModelForm): class Meta: model = MyModel widgets = { 'myfk' : AutoCompleteSelect2Widget(MyModelLookup, placeholder='select related item') }
Warning
As of version 0.4.0 django-selectable-select2 doesn't include any static files dependencies for select2 itself. Use django-staticfiles-select2 and/or django-staticfiles-jquery if you don't have them already in your project.
You can mannually include those assets (assuming you're using django-staticfiles). Like so:
<html> <head> <link rel="stylesheet" href="{{ STATIC_URL }}staticfiles_select2/select2/select2.css"> </head> <body> <form action="." method="post"> {{ form.as_p }} <p><button type="submit">Submit</button></p> </form> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> <script type="text/javascript" src="{{ STATIC_URL }}staticfiles_select2/select2/select2.min.js"></script> <script type="text/javascript" src="{{ STATIC_URL }}selectable_select2/js/jquery.dj.selectable.select2.js"></script> </body> </html>
There is a way to do chained selects in django-selectable. Check out the docs about chained selects to correctly prepare your lookup classes for this use case (you can skip the javascript part). Django-selectable-select2 provides a helper class to declare dependencies of your chained selects on your form.
So given the lookup, from the above link and assuming that MyModel has ForeignKeys
for city and state, your form class can inherit from Select2DependencyModelForm
and define select2_deps
attribute like this:
from selectable_select2.forms import Select2DependencyModelForm from django import forms from selectable_select2.widgets import AutoCompleteSelect2Widget class ChainedForm(Select2DependencyModelForm): select2_deps = ( ('city', { 'parents' : ['state'] }), ) class Meta: model = MyModel widgets = { 'city' : AutoCompleteSelect2Widget(CityLookup, placeholder='select city') }
There is also Select2DependencyForm
which is suitable for non-model based forms.
Note
Both Select2DependencyModelForm
and Select2DependencyForm
in selectable_select2.forms
module inherit from a general class called
Select2DependencyFormMixin
which defines one method called apply_select2_deps
.
Don't hesitate to browse the source of those classes.
select2_deps
is a tuple of two-tuples in form ('<fieldname>' : { <options dict> })
where the options dict is a Python dictionary that configurates the dependencies for that field.
Reference for the options dict:
- parents
- List of field names that are superior for the given field. Like in the above example you can choose a city depending on what state you've chosen. The field can be dependant from more than one parent. Defaults to: [].
- clearonparentchange
- Boolean (True/False) that indicates whether a field should be cleared when a user changes the selection/value of one of it's parents. Defaults to: True.
- parents_namemap
A convenient option (python dictionary) for indicating which key name is sent via ajax for which parent. E.g. Assume that field
child
depends onparent1
andparent2
in our chained selects. You can specify:select2_deps = ( ('child', { parents : ['parent1', 'parent2' ] parents_namemap : { 'parent1' : 'parent', 'parent2' : 'parent' } }), )
Then your lookup can be cleaner and you can search only for
parent
key instead of juggling withparent1
andparent2
in yourget_query
method. Defaults to: {}.
Check the example project for more details.
check out TODO.rst
The minimal version of django-selectable that is required for this app is 0.7
A BIG THANK YOU goes to Igor Vaynberg (select2) and Mark Lavin (django-selectable) for their projects, their support and quick response time in resolving my issues.