From 8bd4106f4e3a9a0dfa6c609c56a801ffd4f7c749 Mon Sep 17 00:00:00 2001
From: "J.-S. Caux" <J.S.Caux@uva.nl>
Date: Thu, 1 Jul 2021 19:48:34 +0200
Subject: [PATCH] Fire up basic PubFraction API

---
 scipost_django/api/urls.py                    |  3 +-
 .../journals/serializers/__init__.py          |  2 +
 .../journals/serializers/pubfraction.py       | 30 +++++++++++++
 .../journals/serializers/publication.py       | 14 ++++++
 scipost_django/journals/viewsets/__init__.py  |  1 +
 .../journals/viewsets/pubfraction.py          | 45 +++++++++++++++++++
 .../organizations/api/serializers.py          | 14 ++++++
 7 files changed, 108 insertions(+), 1 deletion(-)
 create mode 100644 scipost_django/journals/serializers/pubfraction.py
 create mode 100644 scipost_django/journals/viewsets/pubfraction.py

diff --git a/scipost_django/api/urls.py b/scipost_django/api/urls.py
index 5422a80a5..197189b25 100644
--- a/scipost_django/api/urls.py
+++ b/scipost_django/api/urls.py
@@ -7,7 +7,7 @@ from django.urls import include, path
 
 from rest_framework import routers
 
-from journals.viewsets import PublicationViewSet
+from journals.viewsets import PublicationViewSet, PubFractionViewSet
 from organizations.api.viewsets import OrganizationViewSet, OrganizationNAPViewSet
 from submissions.viewsets import SubmissionViewSet
 
@@ -24,6 +24,7 @@ router = routers.SimpleRouter()
 
 # journals
 router.register('publications', PublicationViewSet)
+router.register('pubfractions', PubFractionViewSet)
 
 # organizations
 router.register('organizations', OrganizationViewSet)
diff --git a/scipost_django/journals/serializers/__init__.py b/scipost_django/journals/serializers/__init__.py
index b2c066a21..1281e63f6 100644
--- a/scipost_django/journals/serializers/__init__.py
+++ b/scipost_django/journals/serializers/__init__.py
@@ -3,3 +3,5 @@ __license__ = "AGPL v3"
 
 
 from .publication import PublicationSerializer
+
+from .pubfraction import PubFractionSerializer
diff --git a/scipost_django/journals/serializers/pubfraction.py b/scipost_django/journals/serializers/pubfraction.py
new file mode 100644
index 000000000..9131a0888
--- /dev/null
+++ b/scipost_django/journals/serializers/pubfraction.py
@@ -0,0 +1,30 @@
+__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
+__license__ = "AGPL v3"
+
+
+from rest_framework import serializers
+
+from ..models import OrgPubFraction
+from journals.serializers import PublicationSerializer
+from organizations.api.serializers import OrganizationSerializer
+
+
+class PubFractionSerializer(serializers.ModelSerializer):
+    organization = OrganizationSerializer(
+        fields=['url', 'name', 'acronym', 'country']
+    )
+    publication = PublicationSerializer(
+        fields=[
+            'url',
+            'title', 'author_list',
+            'doi_label', 'publication_date'
+        ]
+    )
+
+    class Meta:
+        model = OrgPubFraction
+        fields = [
+            'organization',
+            'publication',
+            'fraction'
+        ]
diff --git a/scipost_django/journals/serializers/publication.py b/scipost_django/journals/serializers/publication.py
index 59d16a85d..f39f839d4 100644
--- a/scipost_django/journals/serializers/publication.py
+++ b/scipost_django/journals/serializers/publication.py
@@ -20,3 +20,17 @@ class PublicationSerializer(serializers.ModelSerializer):
             'publication_date',
             'url'
         ]
+
+    def __init__(self, *args, **kwargs):
+        # Don't pass the 'fields' arg up to the superclass
+        fields = kwargs.pop('fields', None)
+
+        # Instantiate the superclass normally
+        super().__init__(*args, **kwargs)
+
+        if fields is not None:
+            # Drop any fields that are not specified in the `fields` argument.
+            allowed = set(fields)
+            existing = set(self.fields)
+            for field_name in existing - allowed:
+                self.fields.pop(field_name)
diff --git a/scipost_django/journals/viewsets/__init__.py b/scipost_django/journals/viewsets/__init__.py
index 0310997aa..1087946c3 100644
--- a/scipost_django/journals/viewsets/__init__.py
+++ b/scipost_django/journals/viewsets/__init__.py
@@ -3,3 +3,4 @@ __license__ = "AGPL v3"
 
 
 from .publication import PublicationViewSet
+from .pubfraction import PubFractionViewSet
diff --git a/scipost_django/journals/viewsets/pubfraction.py b/scipost_django/journals/viewsets/pubfraction.py
new file mode 100644
index 000000000..8af8e83f7
--- /dev/null
+++ b/scipost_django/journals/viewsets/pubfraction.py
@@ -0,0 +1,45 @@
+__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
+__license__ = "AGPL v3"
+
+
+from django_filters import rest_framework as df_filters
+
+from rest_framework import viewsets
+from rest_framework.permissions import AllowAny
+
+from api.viewsets.mixins import FilteringOptionsActionMixin
+
+from ..models import OrgPubFraction
+from ..serializers import PubFractionSerializer
+
+
+class PubFractionFilterSet(df_filters.FilterSet):
+    class Meta:
+        model = OrgPubFraction
+        fields = {
+            'organization__name': ['icontains', 'istartswith', 'exact'],
+            'organization__country': ['exact',],
+            'publication__publication_date': [
+                'year', 'month', 'exact',
+                'year__gte', 'year__lte', 'year__range',
+                'gte', 'lte', 'range'
+            ],
+            'fraction': ['gte', 'lte', 'exact']
+        }
+
+
+class PubFractionViewSet(FilteringOptionsActionMixin,
+                         viewsets.ReadOnlyModelViewSet):
+    queryset = OrgPubFraction.objects.all()
+    permission_classes = [AllowAny,]
+    serializer_class = PubFractionSerializer
+    search_fields = [
+        'organization__name',
+        'publication__publication_date__year'
+    ]
+    ordering_fields = ['-publication_date',]
+    filterset_class = PubFractionFilterSet
+    default_filtering_fields = [
+        'organization__name__icontains',
+        'publication__publication_date__year__exact',
+    ]
diff --git a/scipost_django/organizations/api/serializers.py b/scipost_django/organizations/api/serializers.py
index 6864e040d..004d556a2 100644
--- a/scipost_django/organizations/api/serializers.py
+++ b/scipost_django/organizations/api/serializers.py
@@ -29,6 +29,20 @@ class OrganizationSerializer(serializers.ModelSerializer):
             'superseded_by',
         ]
 
+    def __init__(self, *args, **kwargs):
+        # Don't pass the 'fields' arg up to the superclass
+        fields = kwargs.pop('fields', None)
+
+        # Instantiate the superclass normally
+        super().__init__(*args, **kwargs)
+
+        if fields is not None:
+            # Drop any fields that are not specified in the `fields` argument.
+            allowed = set(fields)
+            existing = set(self.fields)
+            for field_name in existing - allowed:
+                self.fields.pop(field_name)
+
 
 class OrganizationNAPSerializer(OrganizationSerializer):
     nap = serializers.SerializerMethodField()
-- 
GitLab