Upgrading from django-autocomplete-light v1 to v2¶
Please enjoy this v1 to v2 upgrade instructions to upgrade from DAL 1.x to 2.x (documented with love !).
Quick upgrade¶
- the Autocomplete class design hasn’t changed at all.
yourlabsWidget()
doesn’t parsesdata-*
options the same,- the django/form python code has been re-organised ie.
get_widgets_dict()
is gone andautocomplete_light.ModelForm
wraps around all features by default. - use
autocomplete_light.ModelForm
instead ofautocomplete_light.GenericModelForm
- generic foreign keys and django-generic-m2m are supported by default if installed.
Detailed upgrade¶
You should not use widget directly anymore¶
We used to have things like this:
class YourForm(autocomplete_light.GenericModelForm):
user = forms.ModelChoiceField(User.objects.all(),
widget=autocomplete_light.ChoiceWidget('UserAutocomplete'))
related = GenericModelChoiceField(
widget=autocomplete_light.ChoiceWidget(
autocomplete='AutocompleteTaggableItems',
autocomplete_js_attributes={'minimum_characters': 0}))
class Meta:
model = YourModel
This caused several problems:
- broke a DRY principle: if you have defined a
user
foreign key and registered an Autocomplete for the model in question,User
, then you should not have to repeat this. - broke the DRY principle since you had to set choices on both the
ModelChoiceField and the Autocomplete -
UserAutocomplete
in this example. - also, validation was done in the widget’s
render()
function, mostly for security reasons. Validation is not done in the widget anymore, instead it is done inautocomplete_light.fields
.
What should the above code be like ? Well it depends, it could just be:
class YourForm(autocomplete_light.ModelForm):
class Meta:
model = YourModel
If you have registered an Autocomplete for the model that the user
ForeignKey is for, then autocomplete_light.ModelForm
will pick it up
automatically.
Assuming you have registered a generic autocomplete,
autocomplete_light.ModelForm
will pick it up automatically.
If you want Django’s default behavior back (using a <select>
tag), then you
could tell autocomplete_light.ModelForm
to not be “autocomplete-aware” for
user
as such:
class YourForm(autocomplete_light.ModelForm):
class Meta:
model = YourModel
autocomplete_exclude = ('user',)
autocomplete_light.ModelChoiceField
and
autocomplete_light.GenericModelChoiceField
:
class YourForm(autocomplete_light.ModelForm):
user = autocomplete_light.ModelChoiceField('UserAutocomplete')
related = autocomplete_light.GenericModelChoiceField('AutocompleteTaggableItems')
class Meta:
model = YourModel
autocomplete_exclude = ('user',)
You can still override widgets the same way as before, but you should consider the DRY breaking implications (which are not specific to django-autocomplete-light, but Django’s design in general).
Specification of the Autocomplete class to use¶
New rules are:
- if an Autocomplete class was registered for a model then it becomes the default Autocomplete class for autocompletion on that model,
- other Autocomplete classes registered for a model will not be used by default
You can still define the Autocomplete class you want in the field definition:
class FooForm(autocomplete_light.ModelForm):
bar = autocomplete_light.ModelChoiceField('SpecialBarAutocomplete')
class Meta:
model = Foo
But this will break some break django DRY logic. Instead, this won’t break DRY:
class FooForm(autocomplete_light.ModelForm):
class Meta:
model = Foo
autocomplete_names = {'bar': 'SpecialBarAutocomplete'}
Python class re-organisation¶
Form classes like FixedModelform
or GenericModelForm
were
renamed. But if you can, just inherit from
autocomplete_light.ModelForm
instead.
Generic field classes were moved from
autocomplete_light.contrib.generic_m2m
into
autocomplete_light.fields
: just import
autocomplete_light.GenericModelChoiceField
and
autocomplete_light.GenericModelMultipleChoiceField <autocomplete_light.fields.GenericModelMultipleChoiceField
.
Deprecation of autocomplete_js_attributes
and widget_js_attributes
¶
In the past, we used autocomplete_js_attributes
and
widget_js_attributes
. Those are deprecated and HTML data
attributes should be used instead.
For example:
class PersonAutocomplete(autocomplete_light.AutocompleteModelBase):
model = Person
autocomplete_js_attributes = {
'minimum_characters': 0,
'placeholder': 'foo',
}
widget_js_attributes = {'max_values': 3}
Should now be:
class PersonAutocomplete(autocomplete_light.AutocompleteModelBase):
model = Person
attrs = {
'data-autcomplete-minimum-characters': 0,
'placeholder': 'foo',
}
widget_attrs = {'data-widget-maximum-values': 3}
As you probably understand already magic inside
autocomplete_js_attributes
and widget_js_attributes
is gone,
we’re just setting plain simple HTML attributes now with attrs
.
Also notice the other two differences which are detailed below:
max-values
was renamed tomaximum-values
(see below)data-autocomplete-placeholder
is gone in favor of HTML5placeholder
attribute (see below)
max-values
was renamed to maximum-values
¶
For consistency with one of my naming conventions which is: no abbreviations.
data-autocomplete-placeholder
is gone in favor of HTML5 placeholder
attribute¶
It made no sense to keep data-autocomplete-placeholder
since we now
have the HTML5 placeholder
attribute.
Widget template changes¶
This is a side effect from the deprecation of
autocomplete_js_attributes
and widget_js_attributes
.
This:
<span class="autocomplete-light-widget {{ name }}
{% if widget.widget_js_attributes.max_values == 1 %}single{% else %}multiple{% endif %}"
id="{{ widget.html_id }}-wrapper"
{{ widget.widget_js_attributes|autocomplete_light_data_attributes }}
{{ widget.autocomplete_js_attributes|autocomplete_light_data_attributes:'autocomplete-' }}
>
Is now:
<span id="{{ widget.html_id }}-wrapper" {{ widget_attrs }} >
Script changes¶
.yourlabsWidget()
used to parse data-*
attributes:
data-foo-bar
used to set the JS attributeyourlabs.Widget.fooBar
,data-autocomplete-foo-bar
used to set the JS attributeyourlabs.Widget.autocomplete.fooBar
.
Now:
.yourlabsWidget()
parsesdata-widget-*
attributes and,.yourlabsAutocomplete()
parsesdata-autocomplete-*
on the ``<input />`` !
So this:
<span class="autocomplete-light-widget" data-autocomplete-foo-bar="2" data-foo-bar="3">
<input .. />
Becomes:
<span class="autocomplete-light-widget" data-widget-foo-bar="3">
<input data-autocomplete-foo-bar="2" ... />
.choiceDetail
and .choiceUpdate
were renamed to .choice-detail
and .choice-update
¶
This makes the CSS class names standard.