mirror of
https://github.com/Hopiu/django-select2.git
synced 2026-03-17 05:50:23 +00:00
Impooved cacheing to reduce pickling issues
Not not the entire widget gets cached nor the entire queryset. The query and gets pickeld separately.
This commit is contained in:
parent
dc81c2b3b5
commit
75c8c38e2d
3 changed files with 39 additions and 12 deletions
|
|
@ -300,7 +300,25 @@ class ModelSelect2Mixin(object):
|
|||
defaults.update(kwargs)
|
||||
super(ModelSelect2Mixin, self).__init__(*args, **defaults)
|
||||
|
||||
def filter_queryset(self, term):
|
||||
def set_to_cache(self):
|
||||
"""
|
||||
Add widget's attributes to Djnago's cache.
|
||||
|
||||
Split the queryset, to not pickle the result set.
|
||||
"""
|
||||
queryset = self.get_queryset()
|
||||
cache.set(self._get_cache_key(), {
|
||||
'queryset':
|
||||
[
|
||||
queryset.none(),
|
||||
queryset.query,
|
||||
],
|
||||
'cls': self.__class__,
|
||||
'search_fields': self.search_fields,
|
||||
'max_results': self.max_results,
|
||||
})
|
||||
|
||||
def filter_queryset(self, term, queryset=None):
|
||||
"""
|
||||
Return queryset filtered by search_fields matching the passed term.
|
||||
|
||||
|
|
@ -309,7 +327,8 @@ class ModelSelect2Mixin(object):
|
|||
:return: Filtered queryset
|
||||
:rtype: :class:`.django.db.models.QuerySet`
|
||||
"""
|
||||
qs = self.get_queryset()
|
||||
if not queryset:
|
||||
queryset = self.get_queryset()
|
||||
search_fields = self.get_search_fields()
|
||||
select = Q()
|
||||
term = term.replace('\t', ' ')
|
||||
|
|
@ -317,7 +336,7 @@ class ModelSelect2Mixin(object):
|
|||
for t in [t for t in term.split(' ') if not t == '']:
|
||||
select &= reduce(lambda x, y: x | Q(**{y: t}), search_fields,
|
||||
Q(**{search_fields.pop(): t}))
|
||||
return qs.filter(select).distinct()
|
||||
return queryset.filter(select).distinct()
|
||||
|
||||
def get_queryset(self):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ class AutoResponseView(BaseListView):
|
|||
|
||||
def get_queryset(self):
|
||||
"""Get queryset from cached widget."""
|
||||
return self.widget.filter_queryset(self.term)
|
||||
return self.widget.filter_queryset(self.term, self.queryset)
|
||||
|
||||
def get_paginate_by(self, queryset):
|
||||
"""Paginate response by size of widget's `max_results` parameter."""
|
||||
|
|
@ -76,7 +76,11 @@ class AutoResponseView(BaseListView):
|
|||
raise Http404('Invalid "field_id".')
|
||||
else:
|
||||
cache_key = '%s%s' % (settings.SELECT2_CACHE_PREFIX, key)
|
||||
widget = cache.get(cache_key)
|
||||
if widget is None:
|
||||
widget_dict = cache.get(cache_key)
|
||||
if widget_dict is None:
|
||||
raise Http404('field_id not found')
|
||||
return widget
|
||||
qs, qs.query = widget_dict.pop('queryset')
|
||||
self.queryset = qs.all()
|
||||
widget_dict['queryset'] = self.queryset
|
||||
widget_cls = widget_dict.pop('cls')
|
||||
return widget_cls(**widget_dict)
|
||||
|
|
|
|||
|
|
@ -161,13 +161,13 @@ class TestModelSelect2Mixin(TestHeavySelect2Mixin):
|
|||
assert result.exists()
|
||||
|
||||
def test_queryset_kwarg(self):
|
||||
widget = ModelSelect2Widget(queryset=Genre.objects, search_fields=['title__icontains'])
|
||||
widget = ModelSelect2Widget(queryset=Genre.objects.all(), search_fields=['title__icontains'])
|
||||
genre = Genre.objects.last()
|
||||
result = widget.filter_queryset(genre.title)
|
||||
assert result.exists()
|
||||
|
||||
def test_ajax_view_registration(self, client):
|
||||
widget = ModelSelect2Widget(queryset=Genre.objects, search_fields=['title__icontains'])
|
||||
widget = ModelSelect2Widget(queryset=Genre.objects.all(), search_fields=['title__icontains'])
|
||||
widget.render('name', 'value')
|
||||
url = reverse('django_select2-json')
|
||||
genre = Genre.objects.last()
|
||||
|
|
@ -178,16 +178,20 @@ class TestModelSelect2Mixin(TestHeavySelect2Mixin):
|
|||
assert genre.pk in [result['id'] for result in data['results']]
|
||||
|
||||
def test_render(self):
|
||||
widget = ModelSelect2Widget()
|
||||
widget = ModelSelect2Widget(queryset=Genre.objects.all())
|
||||
widget.render('name', 'value')
|
||||
cached_widget = cache.get(widget._get_cache_key())
|
||||
assert isinstance(cached_widget, ModelSelect2Widget)
|
||||
assert cached_widget['max_results'] == widget.max_results
|
||||
assert cached_widget['search_fields'] == widget.search_fields
|
||||
qs = widget.get_queryset()
|
||||
assert isinstance(cached_widget['queryset'][0], qs.__class__)
|
||||
assert text_type(cached_widget['queryset'][1]) == text_type(qs.query)
|
||||
|
||||
|
||||
class TestHeavySelect2TagWidget(TestHeavySelect2Mixin):
|
||||
|
||||
def test_tag_attrs(self):
|
||||
widget = ModelSelect2TagWidget(queryset=Genre.objects, search_fields=['title__icontains'])
|
||||
widget = ModelSelect2TagWidget(queryset=Genre.objects.all(), search_fields=['title__icontains'])
|
||||
output = widget.render('name', 'value')
|
||||
assert 'data-minimum-input-length="1"' in output
|
||||
assert 'data-tags="true"' in output
|
||||
|
|
|
|||
Loading…
Reference in a new issue