diff --git a/django/website/hid/templates/hid/categories_column.html b/django/website/hid/templates/hid/categories_column.html index 709ce07df606e695170a18c3da945e6e1ecfad27..5a224cdbc741390bbecf5a403d3e44a79aadbce8 100644 --- a/django/website/hid/templates/hid/categories_column.html +++ b/django/website/hid/templates/hid/categories_column.html @@ -4,7 +4,7 @@ <option value="" selected="selected">---------</option> {% endif %} {% for cat in categories %} - <option value="{{ cat.0 }}"{% if category == cat.0 %} selected="selected"{% endif %}>{{ cat.0 }}</option> + <option value="{{ cat.0 }}"{% if category == cat.0 %} selected="selected"{% endif %}>{{ cat.1 }}</option> {% endfor %} </select> {% endif %} diff --git a/django/website/hid/tests/views_tests.py b/django/website/hid/tests/views_tests.py index 9ce9cd1399d6e3f3db448ad387049d98572b856e..a283b1e03284d138912b4f62fb9f752266067ed4 100644 --- a/django/website/hid/tests/views_tests.py +++ b/django/website/hid/tests/views_tests.py @@ -128,11 +128,11 @@ def test_get_category_options_uses_terms(): ) view = ViewItems() - options = view.get_category_options(ebola_questions.id) + options = view.get_category_options(ebola_questions.slug) - assert (type_1.name, type_1.long_name) in options - assert (type_2.name, type_2.long_name) in options - assert (type_3.name, type_3.long_name) in options + assert (type_1.name, type_1.name) in options + assert (type_2.name, type_2.name) in options + assert (type_3.name, type_3.name) in options assert (other_term.name, other_term.long_name) not in options @@ -154,14 +154,14 @@ def test_get_category_options_with_no_taxonomy_returns_all(): view = ViewItems() options = view.get_category_options() - assert (type_1.name, type_1.long_name) in options - assert (other_term.name, other_term.long_name) in options + assert (type_1.name, type_1.name) in options + assert (other_term.name, other_term.name) in options @pytest.mark.django_db def test_get_category_options_orders_by_lowercase_name(): # TODO: Rewrite tests to use transport layer - ebola_questions = TaxonomyFactory(name="Ebola Questions") + taxonomy = TaxonomyFactory(name="order_by_lowercase_name_test") test_term_values = [ ('test a1', '1'), ('test b1', '2'), ('test A2', '3'), ('test B2', '4') @@ -170,16 +170,15 @@ def test_get_category_options_orders_by_lowercase_name(): TermFactory( name=test_value[0], long_name=test_value[1], - taxonomy=ebola_questions + taxonomy=taxonomy ) view = ViewItems() - options = view.get_category_options(ebola_questions.id) - # Make sure we are only comparing with out test values! - options = [o for o in options if o in test_term_values] + options = view.get_category_options(taxonomy.slug) # Expected is the list ordered by lowercase short name. - expected = sorted(test_term_values, key=lambda e: e[0].lower()) + expected = [(short, short) for short, long_name in test_term_values] + expected = tuple(sorted(expected, key=lambda e: e[0].lower())) assert options == expected diff --git a/django/website/hid/views.py b/django/website/hid/views.py index 1c1ea9575f57b50505be9692716fed36aa0e7584..f8821f405aa00fb8e25b00c43ecc82ae519d6618 100644 --- a/django/website/hid/views.py +++ b/django/website/hid/views.py @@ -14,7 +14,6 @@ from django.views.generic.base import TemplateView from django_tables2 import SingleTableView from chn_spreadsheet.importer import Importer, SheetImportException -from data_layer.models import Term import transport from transport.exceptions import TransportException from .assets import require_assets @@ -90,26 +89,18 @@ class ViewItems(SingleTableView): def get_queryset(self): return transport.items.list() - def get_category_options(self, categories_id=None): - # TODO: Use data layer - terms = self.get_matching_terms(categories_id) - return tuple((t.name, t.long_name) for t in terms) - - def get_matching_terms(self, categories_id): - if categories_id is None: - return (Term.objects - .extra(select={'name_lower': 'lower(name)'}) - .order_by('name_lower') - .all()) - - return (Term.objects - .extra(select={'name_lower': 'lower(name)'}) - .order_by('name_lower') - .filter(taxonomy__id=categories_id)) + def get_category_options(self, taxonomy_slug=None): + if taxonomy_slug is not None: + terms = transport.terms.list(taxonomy=taxonomy_slug) + else: + terms = transport.terms.list() + terms.sort(key=lambda e: e['name'].lower()) + return tuple((t['name'], t['name']) for t in terms) def get_table(self, **kwargs): - # TODO: Filter on taxonomy - kwargs['categories'] = self.get_category_options() + kwargs['categories'] = self.get_category_options( + QUESTION_TYPE_TAXONOMY + ) return super(ViewItems, self).get_table(**kwargs) def get_context_data(self, **kwargs): @@ -126,9 +117,7 @@ class ViewItems(SingleTableView): ), self._build_action_dropdown_group( label=_('Set question type'), - items=[(short_name, short_name) - for short_name, long_name - in self.get_category_options()], + items=self.get_category_options(QUESTION_TYPE_TAXONOMY), prefix=ADD_CATEGORY_PREFIX ) ] diff --git a/django/website/rest_api/views.py b/django/website/rest_api/views.py index 1b4e59d49a52ae8098495358ac141536e9343773..2ea8627f98554e13976f1145a0e8cd31d087a12f 100644 --- a/django/website/rest_api/views.py +++ b/django/website/rest_api/views.py @@ -92,4 +92,32 @@ class TaxonomyViewSet(viewsets.ModelViewSet): class TermViewSet(viewsets.ModelViewSet): serializer_class = TermSerializer - queryset = Term.objects.all() # Will need to filter by taxonomy eventually + queryset = Term.objects.all() + + def get_queryset(self): + """ Return the query set to fetch terms. + + The request may contain the following + exact match filters: + name: Name of the term + long_name: Long name of the term + taxonomy: Slug of the term's taxonomy + + Returns: + QuerySet: A query set + """ + items = Term.objects.all() + + name = self.request.query_params.get('name', None) + if name is not None: + items = items.filter(name=name) + + long_name = self.request.query_params.get('long_name', None) + if long_name is not None: + items = items.filter(long_name=long_name) + + taxonomy_slug = self.request.query_params.get('taxonomy', None) + if taxonomy_slug is not None: + items = items.filter(taxonomy__slug=taxonomy_slug) + + return items diff --git a/django/website/taxonomies/tests/factories.py b/django/website/taxonomies/tests/factories.py index 8192276617cdf8dfe8b88f59e3c18d0f130ec28f..1dd486070687b8bb301471efa0fce16fbbfdc358 100644 --- a/django/website/taxonomies/tests/factories.py +++ b/django/website/taxonomies/tests/factories.py @@ -19,7 +19,7 @@ class TermFactory(DjangoModelFactory): class Meta: model = Term - django_get_or_create = ('name',) + django_get_or_create = ('name', 'taxonomy') name = fuzzy.FuzzyText() diff --git a/django/website/transport/__init__.py b/django/website/transport/__init__.py index fd7d6a560c116a78e82af74b6ddba919af09a81d..d267d406c3a752471ee52c073a2ae139b75372b8 100644 --- a/django/website/transport/__init__.py +++ b/django/website/transport/__init__.py @@ -1,4 +1,5 @@ import items import taxonomies +import terms -__all__ = ['items', 'taxonomies', ] +__all__ = ['items', 'taxonomies', 'terms'] diff --git a/django/website/transport/terms.py b/django/website/transport/terms.py new file mode 100644 index 0000000000000000000000000000000000000000..2d99757e562b924a52d1d1c3c8d42855c4372ad3 --- /dev/null +++ b/django/website/transport/terms.py @@ -0,0 +1,58 @@ +from django.core.urlresolvers import reverse + +from rest_api.views import TermViewSet +from rest_framework.test import APIRequestFactory +from rest_framework import status + +from .exceptions import TransportException + + +request_factory = APIRequestFactory() + + +def list_url(): + """ Returns the url to obtain the list of terms + + Returns: + str: List of term URL + """ + return reverse('term-list') + + +def get_view(actions): + """ Return the view to perform the given action. + + Args: + actions (dict): Dictionary of actions, eg. + {'get': 'list'} + Returns: + View: A view object + """ + return TermViewSet.as_view(actions) + + +def list(**kwargs): + """ Return a list of Terms + + If keyword arguments are given, they are used + to filter the terms. This can be used to list + the terms in a given taxonomy. + + Args: + **kwargs: Filters + Returns: + list: List of terms + Raises: + TransportException: On transport failure. + 'status_code' is set to the response + status code. + """ + view = get_view(actions={'get': 'list'}) + request = request_factory.get(list_url(), kwargs) + response = view(request) + + if not status.is_success(response.status_code): + response.data['status_code'] = response.status_code + raise TransportException(response.data) + + return response.data diff --git a/django/website/transport/tests/term_list_tests.py b/django/website/transport/tests/term_list_tests.py new file mode 100644 index 0000000000000000000000000000000000000000..d9d13c59fe75ecd6d0c1fb9cebda29bda7ee8dae --- /dev/null +++ b/django/website/transport/tests/term_list_tests.py @@ -0,0 +1,79 @@ +from __future__ import unicode_literals, absolute_import +import pytest + +from taxonomies.tests.factories import TaxonomyFactory, TermFactory +import transport + + +@pytest.mark.django_db +def test_list_terms_returns_terms(): + taxonomy = TaxonomyFactory(name='A test taxonomy') + term = TermFactory(name="A test term", taxonomy=taxonomy) + + terms = transport.terms.list() + terms_as_items = [t.items() for t in terms] + + expected = { + 'taxonomy': taxonomy.slug, + 'name': term.name, + 'long_name': term.long_name + }.items() + + assert expected in terms_as_items + + +@pytest.mark.django_db +def test_list_terms_applies_taxonomy_filter(): + taxonomy = TaxonomyFactory(name='A test taxonomy') + term = TermFactory(name="A test term", taxonomy=taxonomy) + term_2 = TermFactory(name="A second test term", taxonomy=taxonomy) + taxonomy_2 = TaxonomyFactory(name='Another test taxonomy') + TermFactory(name="A third test term", taxonomy=taxonomy_2) + + terms = transport.terms.list(taxonomy=taxonomy.slug) + terms_as_items = [t.items() for t in terms] + + expected = [t.items() for t in [ + { + 'taxonomy': taxonomy.slug, + 'name': term.name, + 'long_name': term.long_name + }, + { + 'taxonomy': taxonomy.slug, + 'name': term_2.name, + 'long_name': term_2.long_name + } + + ]] + + assert len(terms) == 2 + assert sorted(terms_as_items) == sorted(expected) + + +@pytest.mark.django_db +def test_list_terms_applies_name_filter_accross_taxonomies(): + taxonomy = TaxonomyFactory(name='A test taxonomy') + term = TermFactory(name="A test term", taxonomy=taxonomy) + TermFactory(name="Another test term", taxonomy=taxonomy) + taxonomy_2 = TaxonomyFactory(name='Another test taxonomy') + term_2 = TermFactory(name="A test term", taxonomy=taxonomy_2) + + terms = transport.terms.list(name="A test term") + terms_as_items = [t.items() for t in terms] + + expected = [t.items() for t in [ + { + 'taxonomy': taxonomy.slug, + 'name': term.name, + 'long_name': term.long_name + }, + { + 'taxonomy': taxonomy_2.slug, + 'name': term_2.name, + 'long_name': term_2.long_name + } + ]] + + assert len(terms) == 2 + assert sorted(terms_as_items) == sorted(expected)