Skip to content

Commit b7f1c55

Browse files
committed
Merge branch 'release/2.0.0'
2 parents 2195fc9 + 459ba5b commit b7f1c55

31 files changed

+129
-183
lines changed

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
11
# Change Log
22

3+
## [2.0.0]
4+
5+
Dropped support for older versions of Django and Python.
6+
7+
Supported:
8+
9+
- Django >= 2.2
10+
- Python >= 3.6
11+
12+
Updates default frontend libraries to:
13+
* //ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js'
14+
* //code.jquery.com/ui/1.12.1/jquery-ui.js
15+
* //code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css
16+
17+
(These can still be customized if you need to run a different version or use different default css)
18+
19+
Many thanks to @Cabilist and @teelee7133
20+
321
## [1.8.0]
422

523
Added/fixed support for Django 2.2

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,14 @@ Read the full documention here: [outside of the admin](http://django-ajax-select
7171

7272
## Assets included by default
7373

74-
* //ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
75-
* //code.jquery.com/ui/1.10.3/jquery-ui.js
76-
* //code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css
74+
* //ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js'
75+
* //code.jquery.com/ui/1.12.1/jquery-ui.js
76+
* //code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css
7777

7878
## Compatibility
7979

80-
* Django >=1.8, <=3
81-
* Python >=2.7, >=3.5
80+
* Django >=2.2
81+
* Python >=3.6
8282

8383
## Contributors
8484

ajax_select/admin.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@ class AjaxSelectAdmin(admin.ModelAdmin):
77
""" in order to get + popup functions subclass this or do the same hook inside of your get_form """
88

99
def get_form(self, request, obj=None, **kwargs):
10-
form = super(AjaxSelectAdmin, self).get_form(request, obj, **kwargs)
10+
form = super().get_form(request, obj, **kwargs)
1111

1212
autoselect_fields_check_can_add(form, self.model, request.user)
1313
return form
1414

1515

16-
class AjaxSelectAdminInlineFormsetMixin(object):
16+
class AjaxSelectAdminInlineFormsetMixin:
1717

1818
def get_formset(self, request, obj=None, **kwargs):
19-
fs = super(AjaxSelectAdminInlineFormsetMixin, self).get_formset(request, obj, **kwargs)
19+
fs = super().get_formset(request, obj, **kwargs)
2020
autoselect_fields_check_can_add(fs.form, self.model, request.user)
2121
return fs
2222

ajax_select/fields.py

Lines changed: 25 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,19 @@
1-
from __future__ import unicode_literals
2-
31
import json
4-
import sys
52

6-
from ajax_select.registry import registry
73
from django import forms
84
from django.conf import settings
95
from django.contrib.contenttypes.models import ContentType
106
from django.db.models import Model
117
from django.forms.utils import flatatt
128
from django.template.defaultfilters import force_escape
139
from django.template.loader import render_to_string
14-
from django.utils.encoding import force_text
10+
from django.urls import reverse
11+
from django.utils.encoding import force_str
1512
from django.utils.module_loading import import_string
1613
from django.utils.safestring import mark_safe
14+
from django.utils.translation import gettext as _
1715

18-
try:
19-
from six import text_type
20-
except ImportError:
21-
from django.utils.six import text_type
22-
23-
24-
if sys.version_info.major >= 3:
25-
from django.utils.translation import gettext as _
26-
else:
27-
from django.utils.translation import ugettext as _
28-
29-
try:
30-
from django.urls import reverse
31-
except ImportError:
32-
# < django 1.10
33-
from django.core.urlresolvers import reverse
16+
from ajax_select.registry import registry
3417

3518
as_default_help = 'Enter text to search.'
3619

@@ -72,7 +55,7 @@ def __init__(self,
7255
*args,
7356
**kwargs):
7457
self.plugin_options = plugin_options or {}
75-
super(forms.widgets.TextInput, self).__init__(*args, **kwargs)
58+
super().__init__(*args, **kwargs)
7659
self.channel = channel
7760
self.help_text = help_text
7861
self.show_help_text = show_help_text
@@ -93,7 +76,7 @@ def render(self, name, value, attrs=None, renderer=None, **_kwargs):
9376
try:
9477
obj = objs[0]
9578
except IndexError:
96-
raise Exception("%s cannot find object:%s" % (lookup, value))
79+
raise Exception(f"{lookup} cannot find object:{value}")
9780
current_repr = lookup.format_item_display(obj)
9881
initial = [current_repr, obj.pk]
9982

@@ -115,7 +98,7 @@ def render(self, name, value, attrs=None, renderer=None, **_kwargs):
11598
context.update(
11699
make_plugin_options(lookup, self.channel, self.plugin_options, initial))
117100
templates = (
118-
'ajax_select/autocompleteselect_%s.html' % self.channel,
101+
f'ajax_select/autocompleteselect_{self.channel}.html',
119102
'ajax_select/autocompleteselect.html')
120103
out = render_to_string(templates, context)
121104
return mark_safe(out)
@@ -124,7 +107,7 @@ def value_from_datadict(self, data, files, name):
124107
return data.get(name, None)
125108

126109
def id_for_label(self, id_):
127-
return '%s_text' % id_
110+
return f'{id_}_text'
128111

129112

130113
class AutoCompleteSelectField(forms.fields.CharField):
@@ -143,8 +126,7 @@ def __init__(self, channel, *args, **kwargs):
143126
)
144127
widget_kwargs.update(kwargs.pop('widget_options', {}))
145128
kwargs["widget"] = AutoCompleteSelectWidget(**widget_kwargs)
146-
super(AutoCompleteSelectField, self).__init__(
147-
max_length=255, *args, **kwargs)
129+
super().__init__(max_length=255, *args, **kwargs)
148130

149131
def clean(self, value):
150132
if value:
@@ -156,7 +138,7 @@ def clean(self, value):
156138
# out of the scope of this field to do anything more than
157139
# tell you it doesn't exist
158140
raise forms.ValidationError(
159-
"%s cannot find object: %s" % (lookup, value))
141+
f"{lookup} cannot find object: {value}")
160142
return objs[0]
161143
else:
162144
if self.required:
@@ -170,7 +152,7 @@ def has_changed(self, initial, data):
170152
# 1 vs u'1'
171153
initial_value = initial if initial is not None else ''
172154
data_value = data if data is not None else ''
173-
return text_type(initial_value) != text_type(data_value)
155+
return str(initial_value) != str(data_value)
174156

175157

176158
###############################################################################
@@ -192,7 +174,7 @@ def __init__(self,
192174
plugin_options=None,
193175
*args,
194176
**kwargs):
195-
super(AutoCompleteSelectMultipleWidget, self).__init__(*args, **kwargs)
177+
super().__init__(*args, **kwargs)
196178
self.channel = channel
197179

198180
self.help_text = help_text
@@ -245,7 +227,7 @@ def render(self, name, value, attrs=None, renderer=None, **_kwargs):
245227
}
246228
context.update(
247229
make_plugin_options(lookup, self.channel, self.plugin_options, initial))
248-
templates = ('ajax_select/autocompleteselectmultiple_%s.html' % self.channel,
230+
templates = (f'ajax_select/autocompleteselectmultiple_{self.channel}.html',
249231
'ajax_select/autocompleteselectmultiple.html')
250232
out = render_to_string(templates, context)
251233
return mark_safe(out)
@@ -254,8 +236,8 @@ def value_from_datadict(self, data, files, name):
254236
# eg. 'members': ['|229|4688|190|']
255237
return [val for val in data.get(name, '').split('|') if val]
256238

257-
def id_for_label(self, id_):
258-
return '%s_text' % id_
239+
def id_for_label(self, id_, index='0'):
240+
return f'{id_}_text'
259241

260242

261243
class AutoCompleteSelectMultipleField(forms.fields.CharField):
@@ -275,13 +257,13 @@ def __init__(self, channel, *args, **kwargs):
275257
# '' will cause translation to fail
276258
# should be ''
277259
if isinstance(help_text, str):
278-
help_text = force_text(help_text)
260+
help_text = force_str(help_text)
279261
# django admin appends "Hold down "Control",..." to the help text
280262
# regardless of which widget is used. so even when you specify an
281263
# explicit help text it appends this other default text onto the end.
282264
# This monkey patches the help text to remove that
283265
if help_text != '':
284-
if not isinstance(help_text, text_type):
266+
if not isinstance(help_text, str):
285267
# ideally this could check request.LANGUAGE_CODE
286268
translated = help_text.translate(settings.LANGUAGE_CODE)
287269
else:
@@ -315,7 +297,7 @@ def __init__(self, channel, *args, **kwargs):
315297
kwargs['widget'] = AutoCompleteSelectMultipleWidget(**widget_kwargs)
316298
kwargs['help_text'] = help_text
317299

318-
super(AutoCompleteSelectMultipleField, self).__init__(*args, **kwargs)
300+
super().__init__(*args, **kwargs)
319301

320302
def clean(self, value):
321303
if not value and self.required:
@@ -327,8 +309,8 @@ def check_can_add(self, user, model):
327309

328310
def has_changed(self, initial_value, data_value):
329311
# [1, 2] vs [u'1', u'2']
330-
ivs = [text_type(v) for v in (initial_value or [])]
331-
dvs = [text_type(v) for v in (data_value or [])]
312+
ivs = [str(v) for v in (initial_value or [])]
313+
dvs = [str(v) for v in (data_value or [])]
332314
return ivs != dvs
333315

334316

@@ -354,7 +336,7 @@ def __init__(self, channel, *args, **kwargs):
354336
self.show_help_text = kwargs.pop('show_help_text', True)
355337
self.plugin_options = kwargs.pop('plugin_options', {})
356338

357-
super(AutoCompleteWidget, self).__init__(*args, **kwargs)
339+
super().__init__(*args, **kwargs)
358340

359341
def render(self, name, value, attrs=None, renderer=None, **_kwargs):
360342

@@ -381,7 +363,7 @@ def render(self, name, value, attrs=None, renderer=None, **_kwargs):
381363
}
382364
context.update(
383365
make_plugin_options(lookup, self.channel, self.plugin_options, initial))
384-
templates = ('ajax_select/autocomplete_%s.html' % self.channel,
366+
templates = (f'ajax_select/autocomplete_{self.channel}.html',
385367
'ajax_select/autocomplete.html')
386368
return mark_safe(render_to_string(templates, context))
387369

@@ -409,7 +391,7 @@ def __init__(self, channel, *args, **kwargs):
409391
defaults = {'max_length': 255, 'widget': widget}
410392
defaults.update(kwargs)
411393

412-
super(AutoCompleteField, self).__init__(*args, **defaults)
394+
super().__init__(*args, **defaults)
413395

414396

415397
###############################################################################
@@ -429,12 +411,12 @@ def _check_can_add(self, user, related_model):
429411
can_add = lookup.can_add(user, related_model)
430412
else:
431413
ctype = ContentType.objects.get_for_model(related_model)
432-
can_add = user.has_perm("%s.add_%s" % (ctype.app_label, ctype.model))
414+
can_add = user.has_perm(f"{ctype.app_label}.add_{ctype.model}")
433415
if can_add:
434416
app_label = related_model._meta.app_label
435417
model = related_model._meta.object_name.lower()
436418
self.widget.add_link = reverse(
437-
'admin:%s_%s_add' % (app_label, model)) + '?_popup=1'
419+
f'admin:{app_label}_{model}_add') + '?_popup=1'
438420

439421

440422
def autoselect_fields_check_can_add(form, model, user):

ajax_select/helpers.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
from django.db.models.fields.related import ForeignKey, ManyToManyField
22
from django.forms.models import ModelForm
3-
from django.utils.encoding import force_text
3+
from django.utils.encoding import force_str
44
from django.utils.text import capfirst
5-
from django.utils.translation import ugettext_lazy as _
5+
from django.utils.translation import gettext_lazy as _
66

77

88
def make_ajax_form(model, fieldlist, superclass=ModelForm, show_help_text=False, **kwargs):
@@ -89,7 +89,7 @@ def make_ajax_field(related_model, fieldname_on_model, channel, show_help_text=F
8989

9090
field = related_model._meta.get_field(fieldname_on_model)
9191
if 'label' not in kwargs:
92-
kwargs['label'] = _(capfirst(force_text(field.verbose_name)))
92+
kwargs['label'] = _(capfirst(force_str(field.verbose_name)))
9393

9494
if ('help_text' not in kwargs) and field.help_text:
9595
kwargs['help_text'] = field.help_text

ajax_select/lookup_channel.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
from django.core.exceptions import PermissionDenied
2-
from django.utils.encoding import force_text
2+
from django.utils.encoding import force_str
33
from django.utils.html import escape
44

55

6-
class LookupChannel(object):
6+
class LookupChannel:
77
"""
88
Subclass this, setting the model and implementing methods to taste.
99
@@ -40,7 +40,7 @@ def get_query(self, q, request):
4040
Returns:
4141
(QuerySet, list, generator): iterable of related_models
4242
"""
43-
kwargs = {"%s__icontains" % self.search_field: q}
43+
kwargs = {f"{self.search_field}__icontains": q}
4444
return self.model.objects.filter(**kwargs).order_by(self.search_field)
4545

4646
def get_result(self, obj):
@@ -60,7 +60,7 @@ def get_result(self, obj):
6060
Returns:
6161
str: The object as string
6262
"""
63-
return escape(force_text(obj))
63+
return escape(force_str(obj))
6464

6565
def format_match(self, obj):
6666
"""
@@ -71,7 +71,7 @@ def format_match(self, obj):
7171
Returns:
7272
str: formatted string, may contain HTML.
7373
"""
74-
return escape(force_text(obj))
74+
return escape(force_str(obj))
7575

7676
def format_item_display(self, obj):
7777
"""
@@ -82,7 +82,7 @@ def format_item_display(self, obj):
8282
Returns:
8383
str: formatted string, may contain HTML.
8484
"""
85-
return escape(force_text(obj))
85+
return escape(force_str(obj))
8686

8787
def get_objects(self, ids):
8888
"""
@@ -123,7 +123,7 @@ def can_add(self, user, other_model):
123123
"""
124124
from django.contrib.contenttypes.models import ContentType
125125
ctype = ContentType.objects.get_for_model(other_model)
126-
return user.has_perm("%s.add_%s" % (ctype.app_label, ctype.model))
126+
return user.has_perm(f"{ctype.app_label}.add_{ctype.model}")
127127

128128
def check_auth(self, request):
129129
"""

ajax_select/registry.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from django.utils.module_loading import autodiscover_modules
55

66

7-
class LookupChannelRegistry(object):
7+
class LookupChannelRegistry:
88
"""
99
Registry for LookupChannels activated for your django project.
1010
@@ -56,7 +56,7 @@ def get(self, channel):
5656
lookup_spec = self._registry[channel]
5757
except KeyError:
5858
raise ImproperlyConfigured(
59-
"No ajax_select LookupChannel named %(channel)r is registered." % {'channel': channel})
59+
f"No ajax_select LookupChannel named {channel!r} is registered.")
6060

6161
if (type(lookup_spec) is type) and issubclass(lookup_spec, LookupChannel):
6262
return lookup_spec()
@@ -77,7 +77,7 @@ def get(self, channel):
7777
lookup_class = getattr(lookup_module, lookup_spec[1])
7878
return lookup_class()
7979
else:
80-
raise Exception("Invalid lookup spec: %s" % lookup_spec)
80+
raise Exception(f"Invalid lookup spec: {lookup_spec}")
8181

8282
def is_registered(self, channel):
8383
return channel in self._registry

0 commit comments

Comments
 (0)