From f482559fbc2ec1c8311f85f0ca58566d5a70cd8f Mon Sep 17 00:00:00 2001
From: Kenzo-Hugo Hillion <kenzo-hugo.hillion1@pasteur.fr>
Date: Thu, 12 Dec 2019 12:41:20 +0100
Subject: [PATCH] allow filtering on version through eggnog API

---
 .../api/catalog/filters/__init__.py           |  2 +-
 .../api/catalog/filters/function.py           |  9 ++-
 .../catalog/qparams_validators/function.py    | 13 ++++
 .../views/{bulk_viewset.py => base.py}        | 75 ++++++++++---------
 .../metagenedb/api/catalog/views/function.py  | 17 +++--
 backend/metagenedb/api/catalog/views/gene.py  |  2 +-
 .../metagenedb/api/catalog/views/taxonomy.py  |  2 +-
 .../{test_bulk_viewset.py => test_base.py}    |  0
 8 files changed, 74 insertions(+), 46 deletions(-)
 rename backend/metagenedb/api/catalog/views/{bulk_viewset.py => base.py} (98%)
 rename backend/metagenedb/api/catalog/views/{test_bulk_viewset.py => test_base.py} (100%)

diff --git a/backend/metagenedb/api/catalog/filters/__init__.py b/backend/metagenedb/api/catalog/filters/__init__.py
index 7ad133f..b00f602 100644
--- a/backend/metagenedb/api/catalog/filters/__init__.py
+++ b/backend/metagenedb/api/catalog/filters/__init__.py
@@ -1,3 +1,3 @@
-from .function import FunctionFilter  # noqa
+from .function import EggNOGFilter, FunctionFilter  # noqa
 from .gene import GeneFilter  # noqa
 from .taxonomy import TaxonomyFilter  # noqa
diff --git a/backend/metagenedb/api/catalog/filters/function.py b/backend/metagenedb/api/catalog/filters/function.py
index 963f19d..735fdc2 100644
--- a/backend/metagenedb/api/catalog/filters/function.py
+++ b/backend/metagenedb/api/catalog/filters/function.py
@@ -1,5 +1,5 @@
 from django_filters import rest_framework as filters
-from metagenedb.apps.catalog.models import Function
+from metagenedb.apps.catalog.models import Function, EggNOG
 
 
 class FunctionFilter(filters.FilterSet):
@@ -7,3 +7,10 @@ class FunctionFilter(filters.FilterSet):
     class Meta:
         model = Function
         fields = ['source']
+
+
+class EggNOGFilter(filters.FilterSet):
+
+    class Meta:
+        model = EggNOG
+        fields = ['version']
diff --git a/backend/metagenedb/api/catalog/qparams_validators/function.py b/backend/metagenedb/api/catalog/qparams_validators/function.py
index b95b016..80a17dc 100644
--- a/backend/metagenedb/api/catalog/qparams_validators/function.py
+++ b/backend/metagenedb/api/catalog/qparams_validators/function.py
@@ -1,7 +1,20 @@
 from marshmallow import fields
+from marshmallow.validate import OneOf
 
+from metagenedb.apps.catalog import models
 from metagenedb.common.django_default.qparams_validators import PaginatedQueryParams
 
+SELECTED_SOURCE = [i[0] for i in models.Function.SOURCE_CHOICES]
+EGGNOG_VERSIONS = [i[0] for i in models.EggNOG.VERSION_CHOICES]
+
 
 class FunctionQueryParams(PaginatedQueryParams):
+    source = fields.String(validate=OneOf(choices=SELECTED_SOURCE))
+
+
+class KeggQueryParams(PaginatedQueryParams):
     detailed = fields.Boolean()
+
+
+class EggNOGQueryParams(PaginatedQueryParams):
+    version = fields.String(validate=OneOf(choices=EGGNOG_VERSIONS))
diff --git a/backend/metagenedb/api/catalog/views/bulk_viewset.py b/backend/metagenedb/api/catalog/views/base.py
similarity index 98%
rename from backend/metagenedb/api/catalog/views/bulk_viewset.py
rename to backend/metagenedb/api/catalog/views/base.py
index ce82fa9..62e2f0e 100644
--- a/backend/metagenedb/api/catalog/views/bulk_viewset.py
+++ b/backend/metagenedb/api/catalog/views/base.py
@@ -7,16 +7,51 @@ from metagenedb.common.django_default.permissions import ListAndRetrieveAll
 from metagenedb.common.django_default.qparams_validators import PaginatedQueryParams
 
 
-class BulkViewSet(ModelViewSet):
+class QParamsValidationViewSet(ModelViewSet):
     query_params_parser = PaginatedQueryParams
+
+    def _get_qparams(self, raw_query_params):
+        return self.query_params_parser().load(raw_query_params)
+
+    def list(self, request, *args, **kwargs):
+        try:
+            query_params = self._get_qparams(request.query_params)  # noqa
+        except ValidationError as validation_error:
+            error_message = validation_error.normalized_messages()
+            error_message.update({
+                'allowed_query_params': ', '.join(self.query_params_parser().declared_fields.keys())
+            })
+            return Response(error_message, status=status.HTTP_422_UNPROCESSABLE_ENTITY)
+        queryset = self.filter_queryset(self.get_queryset())
+
+        page = self.paginate_queryset(queryset)
+        if page is not None:
+            serializer = self.get_serializer(page, many=True)
+            return self.get_paginated_response(serializer.data)
+
+        serializer = self.get_serializer(queryset, many=True)
+        return Response(serializer.data)
+
+    def retrieve(self, request, *args, **kwargs):
+        try:
+            query_params = self._get_qparams(request.query_params)  # noqa
+        except ValidationError as validation_error:
+            error_message = validation_error.normalized_messages()
+            error_message.update({
+                'allowed_query_params': ', '.join(self.query_params_parser().declared_fields.keys())
+            })
+            return Response(error_message, status=status.HTTP_422_UNPROCESSABLE_ENTITY)
+        instance = self.get_object()
+        serializer = self.get_serializer(instance)
+        return Response(serializer.data)
+
+
+class BulkViewSet(QParamsValidationViewSet):
     permission_classes = [ListAndRetrieveAll]
 
     def get_objects(self, instance_ids):
         return self.queryset.in_bulk(instance_ids, field_name=self.lookup_field)
 
-    def _get_qparams(self, raw_query_params):
-        return self.query_params_parser().load(raw_query_params)
-
     def _created_payload(self, serializer, request):
         if isinstance(request.data, list):
             return {
@@ -83,35 +118,3 @@ class BulkViewSet(ModelViewSet):
             self._updated_payload(create_serializer, update_serializer, request),
             status=status.HTTP_201_CREATED, headers=headers
         )
-
-    def list(self, request, *args, **kwargs):
-        try:
-            query_params = self._get_qparams(request.query_params)  # noqa
-        except ValidationError as validation_error:
-            error_message = validation_error.normalized_messages()
-            error_message.update({
-                'allowed_query_params': ', '.join(self.query_params_parser().declared_fields.keys())
-            })
-            return Response(error_message, status=status.HTTP_422_UNPROCESSABLE_ENTITY)
-        queryset = self.filter_queryset(self.get_queryset())
-
-        page = self.paginate_queryset(queryset)
-        if page is not None:
-            serializer = self.get_serializer(page, many=True)
-            return self.get_paginated_response(serializer.data)
-
-        serializer = self.get_serializer(queryset, many=True)
-        return Response(serializer.data)
-
-    def retrieve(self, request, *args, **kwargs):
-        try:
-            query_params = self._get_qparams(request.query_params)  # noqa
-        except ValidationError as validation_error:
-            error_message = validation_error.normalized_messages()
-            error_message.update({
-                'allowed_query_params': ', '.join(self.query_params_parser().declared_fields.keys())
-            })
-            return Response(error_message, status=status.HTTP_422_UNPROCESSABLE_ENTITY)
-        instance = self.get_object()
-        serializer = self.get_serializer(instance)
-        return Response(serializer.data)
diff --git a/backend/metagenedb/api/catalog/views/function.py b/backend/metagenedb/api/catalog/views/function.py
index 3dcb685..3a968b1 100644
--- a/backend/metagenedb/api/catalog/views/function.py
+++ b/backend/metagenedb/api/catalog/views/function.py
@@ -5,13 +5,15 @@ from rest_framework.response import Response
 from rest_framework.status import HTTP_422_UNPROCESSABLE_ENTITY
 from rest_framework.viewsets import ModelViewSet
 
-from metagenedb.api.catalog.filters import FunctionFilter
-from metagenedb.api.catalog.qparams_validators.function import FunctionQueryParams
+from metagenedb.api.catalog.filters import FunctionFilter, EggNOGFilter
+from metagenedb.api.catalog.qparams_validators.function import (
+    EggNOGQueryParams, FunctionQueryParams, KeggQueryParams
+)
 from metagenedb.apps.catalog.models import EggNOG, Function, KeggOrthology
 from metagenedb.apps.catalog.serializers import EggNOGSerializer, FunctionSerializer, KeggOrthologySerializer
 from metagenedb.common.utils.external_api.togows import GetFunctionExternalInfo
 
-from .bulk_viewset import BulkViewSet
+from .base import BulkViewSet, QParamsValidationViewSet
 
 
 logger = logging.getLogger(__name__)
@@ -22,13 +24,14 @@ class FunctionViewSet(BulkViewSet):
     serializer_class = FunctionSerializer
     lookup_field = 'function_id'
     filterset_class = FunctionFilter
+    query_params_parser = FunctionQueryParams
 
 
-class KeggOrthologyViewSet(ModelViewSet):
+class KeggOrthologyViewSet(QParamsValidationViewSet):
     queryset = KeggOrthology.objects.all()
     serializer_class = KeggOrthologySerializer
     lookup_field = 'function_id'
-    query_params_parser = FunctionQueryParams
+    query_params_parser = KeggQueryParams
 
     def _get_external_info(self, db_data):
         detailed_info_retriever = GetFunctionExternalInfo(db_data['function_id'], 'kegg')
@@ -57,7 +60,9 @@ class KeggOrthologyViewSet(ModelViewSet):
         return Response(returned_data)
 
 
-class EggNOGViewSet(ModelViewSet):
+class EggNOGViewSet(QParamsValidationViewSet):
     queryset = EggNOG.objects.all()
     serializer_class = EggNOGSerializer
     lookup_field = 'function_id'
+    filterset_class = EggNOGFilter
+    query_params_parser = EggNOGQueryParams
diff --git a/backend/metagenedb/api/catalog/views/gene.py b/backend/metagenedb/api/catalog/views/gene.py
index 8a2aadf..6189e74 100644
--- a/backend/metagenedb/api/catalog/views/gene.py
+++ b/backend/metagenedb/api/catalog/views/gene.py
@@ -14,7 +14,7 @@ from metagenedb.api.catalog.filters import GeneFilter
 from metagenedb.api.catalog.qparams_validators.gene import GeneLengthQueryParams, GeneQueryParams, TaxCountQueryParams
 from metagenedb.apps.catalog.serializers import GeneSerializer
 
-from .bulk_viewset import BulkViewSet
+from .base import BulkViewSet
 
 
 class DocGeneLength(object):
diff --git a/backend/metagenedb/api/catalog/views/taxonomy.py b/backend/metagenedb/api/catalog/views/taxonomy.py
index e6dc49c..c32363a 100644
--- a/backend/metagenedb/api/catalog/views/taxonomy.py
+++ b/backend/metagenedb/api/catalog/views/taxonomy.py
@@ -7,7 +7,7 @@ from metagenedb.api.catalog.qparams_validators.taxonomy import TaxonomyQueryPara
 from metagenedb.apps.catalog.models import Taxonomy
 from metagenedb.apps.catalog.serializers import TaxonomySerializer
 
-from .bulk_viewset import BulkViewSet
+from .base import BulkViewSet
 
 
 class TaxonomyViewSet(BulkViewSet):
diff --git a/backend/metagenedb/api/catalog/views/test_bulk_viewset.py b/backend/metagenedb/api/catalog/views/test_base.py
similarity index 100%
rename from backend/metagenedb/api/catalog/views/test_bulk_viewset.py
rename to backend/metagenedb/api/catalog/views/test_base.py
-- 
GitLab