Skip to content

Commit

Permalink
Feature/esckan-35 - Composer REST new generic endpoint - public - Kno…
Browse files Browse the repository at this point in the history
…wledgeStatement (#260)

* #35 renaming of methods and functions

* #35 rename reference uri to population uri

* #35 use model property instead of repeat logic
  • Loading branch information
D-GopalKrishna authored Apr 11, 2024
1 parent ab27d4c commit 384e2d3
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 1 deletion.
7 changes: 6 additions & 1 deletion backend/composer/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ class SentenceAdmin(
class AnatomicalEntityAdmin(admin.ModelAdmin):
search_fields = ('simple_entity__name', 'region_layer__layer__name', 'region_layer__region__name')
autocomplete_fields = ('simple_entity', 'region_layer')
list_display = ('simple_entity', 'region_layer', "synonyms")
list_display = ('simple_entity', 'region_layer', "synonyms", "ontology_uri")
list_display_links = ('simple_entity', 'region_layer')
inlines = (SynonymInline,)

Expand All @@ -114,6 +114,11 @@ def get_queryset(self, request: HttpRequest) -> QuerySet[Any]:
def synonyms(self, obj):
synonyms = obj.synonyms.all()
return ', '.join([synonym.name for synonym in synonyms])

@admin.display(description="Ontology URI")
def ontology_uri(self, obj):
return obj.ontology_uri



class AnatomicalEntityMetaAdmin(admin.ModelAdmin):
Expand Down
62 changes: 62 additions & 0 deletions backend/composer/api/filtersets.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
Via,
Specie, Destination,
)
from django_filters import rest_framework
from django_filters import CharFilter, BaseInFilter


def field_has_content(queryset, name, value):
Expand Down Expand Up @@ -95,6 +97,66 @@ class Meta:
fields = []


class ListCharFilter(BaseInFilter, CharFilter):
pass


class KnowledgeStatementFilterSet(rest_framework.FilterSet):
via_uris = ListCharFilter(method='filter_via_uris', label='Via URI')
destination_uris = ListCharFilter(method='filter_destination_uris', label='Destination URI')
origin_uris = ListCharFilter(method='filter_origin_uris', label='Origin URI')
population_uris = ListCharFilter(method='filter_population_uris', label='Reference URI')

class Meta:
model = ConnectivityStatement
fields = ['via_uris', 'destination_uris', 'origin_uris', 'population_uris']
distinct = True

@property
def qs(self):
return super().qs.distinct()

def filter_population_uris(self, queryset, name, value):
return queryset.filter(reference_uri__in=value)

def filter_via_uris(self, queryset, name, value):
via_uris = value
via_ids = Via.objects.none()
for uri in via_uris:
via_ids = via_ids.union(
Via.objects.filter(anatomical_entities__simple_entity__ontology_uri=uri).prefetch_related('anatomical_entities__simple_entity')
.union(Via.objects.filter(anatomical_entities__region_layer__layer__ontology_uri=uri).prefetch_related('anatomical_entities__region_layer__layer'))
.union(Via.objects.filter(anatomical_entities__region_layer__region__ontology_uri=uri).prefetch_related('anatomical_entities__region_layer__region'))
.values_list("id", flat=True)
)
return queryset.filter(via__in=via_ids)

def filter_destination_uris(self, queryset, name, value):
destination_uris = value
destination_ids = Destination.objects.none()
for uri in destination_uris:
destination_ids = destination_ids.union(
Destination.objects.filter(anatomical_entities__simple_entity__ontology_uri=uri).prefetch_related('anatomical_entities__simple_entity')
.union(Destination.objects.filter(anatomical_entities__region_layer__layer__ontology_uri=uri).prefetch_related('anatomical_entities__region_layer__layer'))
.union(Destination.objects.filter(anatomical_entities__region_layer__region__ontology_uri=uri).prefetch_related('anatomical_entities__region_layer__region'))
.values_list("id", flat=True)
)
return queryset.filter(destinations__in=destination_ids)

def filter_origin_uris(self, queryset, name, value):
origin_uris = value
origin_ids = AnatomicalEntity.objects.none()
for uri in origin_uris:
origin_ids = origin_ids.union(
AnatomicalEntity.objects.filter(simple_entity__ontology_uri=uri).prefetch_related('simple_entity')
.union(AnatomicalEntity.objects.filter(region_layer__layer__ontology_uri=uri).prefetch_related('region_layer__layer'))
.union(AnatomicalEntity.objects.filter(region_layer__region__ontology_uri=uri).prefetch_related('region_layer__region'))
.values_list("id", flat=True)
)
return queryset.filter(origins__in=origin_ids)



class AnatomicalEntityFilter(django_filters.FilterSet):
name = django_filters.CharFilter(method="filter_name")
exclude_ids = NumberInFilter(field_name='id', exclude=True)
Expand Down
15 changes: 15 additions & 0 deletions backend/composer/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -680,3 +680,18 @@ class Meta:
"errors"
)


class KnowledgeStatementSerializer(ConnectivityStatementSerializer):
"""Knowledge Statement"""
class Meta(ConnectivityStatementSerializer.Meta):
fields = (
"id",
"sentence_id",
"species",
"origins",
"vias",
"destinations",
"apinatomy_model",
"phenotype_id",
"phenotype",
)
2 changes: 2 additions & 0 deletions backend/composer/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
AnatomicalEntityViewSet,
PhenotypeViewSet,
ConnectivityStatementViewSet,
KnowledgeStatementViewSet,
jsonschemas,
NoteViewSet,
ProfileViewSet,
Expand Down Expand Up @@ -42,4 +43,5 @@
urlpatterns = [
path("", include(router.urls)),
path("jsonschemas/", jsonschemas, name="jsonschemas"),
path("knowledge-statement/", KnowledgeStatementViewSet.as_view(), name="knowledge-statement"),
]
32 changes: 32 additions & 0 deletions backend/composer/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
from rest_framework.renderers import INDENT_SEPARATORS
from rest_framework.response import Response
from rest_framework.serializers import ValidationError
from rest_framework import generics
from django_filters.rest_framework import DjangoFilterBackend

from composer.services.state_services import (
ConnectivityStatementStateService,
Expand All @@ -17,6 +19,7 @@
from .filtersets import (
SentenceFilter,
ConnectivityStatementFilter,
KnowledgeStatementFilterSet,
AnatomicalEntityFilter,
NoteFilter,
ViaFilter,
Expand All @@ -26,6 +29,7 @@
AnatomicalEntitySerializer,
PhenotypeSerializer,
ConnectivityStatementSerializer,
KnowledgeStatementSerializer,
NoteSerializer,
ProfileSerializer,
SentenceSerializer,
Expand Down Expand Up @@ -345,6 +349,34 @@ def partial_update(self, request, *args, **kwargs):
return super().partial_update(request, *args, **kwargs)


@extend_schema(tags=["public"])
class KnowledgeStatementViewSet(
generics.ListAPIView,
):
"""
KnowledgeStatement that only allows GET to get the list of ConnectivityStatements
"""
model = ConnectivityStatement
queryset = ConnectivityStatement.objects.exported()
serializer_class = KnowledgeStatementSerializer
permission_classes = [
permissions.AllowAny,
]
filter_backends = [DjangoFilterBackend]
filterset_class = KnowledgeStatementFilterSet

@property
def allowed_methods(self):
return ['GET']

def get_serializer_class(self):
return KnowledgeStatementSerializer


def list(self, request, *args, **kwargs):
return super().list(request, *args, **kwargs)


class TagViewSet(viewsets.ReadOnlyModelViewSet):
"""
Tag
Expand Down
3 changes: 3 additions & 0 deletions backend/composer/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ def get_queryset(self):

def excluding_draft(self):
return self.get_queryset().exclude(state=CSState.DRAFT)

def exported(self):
return self.get_queryset().filter(state=CSState.EXPORTED)


class SentenceStatementManager(models.Manager):
Expand Down

0 comments on commit 384e2d3

Please sign in to comment.