From a913fbe2836b43bd580289eea12e3a1887fcd430 Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Thu, 10 Dec 2015 14:43:34 +0000 Subject: [PATCH] Decouple 'popular tags' filtering on image chooser from search Searching by tag only works under Elasticsearch, so clicking on 'popular tags' is broken in the default install. As a workaround, add a new 'tag' parameter to the chooser view that allows us to filter on tags using plain SQL lookup, as a separate operation to search. --- .../wagtailimages/chooser/chooser.html | 2 +- .../wagtailimages/chooser/chooser.js | 40 +++++++++++-------- .../wagtailimages/tests/test_admin_views.py | 18 +++++++++ wagtail/wagtailimages/views/chooser.py | 15 +++++-- 4 files changed, 53 insertions(+), 22 deletions(-) diff --git a/wagtail/wagtailimages/templates/wagtailimages/chooser/chooser.html b/wagtail/wagtailimages/templates/wagtailimages/chooser/chooser.html index 5f4e3a2278..afa5bc4e3c 100644 --- a/wagtail/wagtailimages/templates/wagtailimages/chooser/chooser.html +++ b/wagtail/wagtailimages/templates/wagtailimages/chooser/chooser.html @@ -22,7 +22,7 @@
  • {% trans 'Popular tags' %}

    {% for tag in popular_tags %} - {{ tag.name }} + {{ tag.name }} {% endfor %}
  • {% endif %} diff --git a/wagtail/wagtailimages/templates/wagtailimages/chooser/chooser.js b/wagtail/wagtailimages/templates/wagtailimages/chooser/chooser.js index c27292f94f..b6061bd005 100644 --- a/wagtail/wagtailimages/templates/wagtailimages/chooser/chooser.js +++ b/wagtail/wagtailimages/templates/wagtailimages/chooser/chooser.js @@ -1,6 +1,10 @@ function(modal) { var searchUrl = $('form.image-search', modal.body).attr('action'); + /* currentTag stores the tag currently being filtered on, so that we can + preserve this when paginating */ + var currentTag; + function ajaxifyLinks (context) { $('.listing a', context).click(function() { modal.loadUrl(this.href); @@ -14,33 +18,34 @@ function(modal) { }); } - function search() { + function fetchResults(requestData) { $.ajax({ url: searchUrl, - data: {q: $('#id_q').val()}, + data: requestData, success: function(data, status) { $('#image-results').html(data); ajaxifyLinks($('#image-results')); } }); + } + + function search() { + /* Searching causes currentTag to be cleared - otherwise there's + no way to de-select a tag */ + currentTag = null; + fetchResults({q: $('#id_q').val()}); return false; } function setPage(page) { - if($('#id_q').val().length){ - dataObj = {q: $('#id_q').val(), p: page}; - }else{ - dataObj = {p: page}; + params = {p: page}; + if ($('#id_q').val().length){ + params['q'] = $('#id_q').val(); } - - $.ajax({ - url: searchUrl, - data: dataObj, - success: function(data, status) { - $('#image-results').html(data); - ajaxifyLinks($('#image-results')); - } - }); + if (currentTag) { + params['tag'] = currentTag; + } + fetchResults(params); return false; } @@ -72,8 +77,9 @@ function(modal) { $(this).data('timer', wait); }); $('a.suggested-tag').click(function() { - $('#id_q').val($(this).text()); - search(); + currentTag = $(this).text(); + $('#id_q').val(''); + fetchResults({'tag': currentTag}); return false; }); diff --git a/wagtail/wagtailimages/tests/test_admin_views.py b/wagtail/wagtailimages/tests/test_admin_views.py index 3726b8b02f..61325172d1 100644 --- a/wagtail/wagtailimages/tests/test_admin_views.py +++ b/wagtail/wagtailimages/tests/test_admin_views.py @@ -299,6 +299,24 @@ class TestImageChooserView(TestCase, WagtailTestUtils): response = self.get({'p': page}) self.assertEqual(response.status_code, 200) + def test_filter_by_tag(self): + for i in range(0, 10): + image = Image.objects.create( + title="Test image %d is even better than the last one" % i, + file=get_test_image_file(), + ) + if i % 2 == 0: + image.tags.add('even') + + response = self.get({'tag': "even"}) + self.assertEqual(response.status_code, 200) + + # Results should include images tagged 'even' + self.assertContains(response, "Test image 2 is even better") + + # Results should not include images that just have 'even' in the title + self.assertNotContains(response, "Test image 3 is even better") + class TestImageChooserChosenView(TestCase, WagtailTestUtils): def setUp(self): diff --git a/wagtail/wagtailimages/views/chooser.py b/wagtail/wagtailimages/views/chooser.py index 57f9b1640c..cee8a89f83 100644 --- a/wagtail/wagtailimages/views/chooser.py +++ b/wagtail/wagtailimages/views/chooser.py @@ -42,16 +42,24 @@ def chooser(request): else: uploadform = None + images = Image.objects.order_by('-created_at') + q = None - if 'q' in request.GET or 'p' in request.GET: + if 'q' in request.GET or 'p' in request.GET or 'tag' in request.GET: + # this request is triggered from search, pagination or 'popular tags'; + # we will just render the results.html fragment + + tag_name = request.GET.get('tag') + if tag_name: + images = images.filter(tags__name=tag_name) + searchform = SearchForm(request.GET) if searchform.is_valid(): q = searchform.cleaned_data['q'] - images = Image.objects.search(q) + images = images.search(q) is_searching = True else: - images = Image.objects.order_by('-created_at') is_searching = False # Pagination @@ -66,7 +74,6 @@ def chooser(request): else: searchform = SearchForm() - images = Image.objects.order_by('-created_at') paginator, images = paginate(request, images, per_page=12) return render_modal_workflow(request, 'wagtailimages/chooser/chooser.html', 'wagtailimages/chooser/chooser.js', {