Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions solid_backend/content/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@
AllNodesFlatEndpoint,
FlatProfilesEndpoint,
AncestorsEndpoint,
ProfileSearchEndpoint,
)

app_name = "content"
router = SimpleRouter()
router.register(r"profile-search", ProfileSearchEndpoint, basename="profile-search")
router.register(r"root-nodes", RootNodeEndpoint, basename="rootnode")
router.register(r"leaf-nodes", LeavesEndpoint, basename="leafnodes")
router.register(r"parent-node", ParentNodeEndpoint, basename="parentnode")
Expand Down
102 changes: 96 additions & 6 deletions solid_backend/content/views.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
from django.db.models import Prefetch, F
from rest_framework.response import Response
from rest_framework.decorators import action
import logging
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.exceptions import ValidationError, ParseError
from rest_framework.viewsets import ReadOnlyModelViewSet, GenericViewSet
from django.db.models import Q
from django.conf import settings
import logging
from importlib import import_module
from solid_backend.media_object.models import MediaObject
from mptt.fields import TreeForeignKey

Expand All @@ -21,8 +17,6 @@
SERIALIZERS,
)

# logger = logging.getLogger(__name__)


class NestedProfileEndpoint(ReadOnlyModelViewSet):
"""
Expand Down Expand Up @@ -268,3 +262,99 @@ def list(self, request):
data["def_type"] = model_name
response_data.append(data)
return Response(response_data)


class SearchNodeWithProfilesEndpoint(ReadOnlyModelViewSet):
"""
Endpoint that returns tree nodes that contain the search term in their general_information__name or general_information__synonyms fields.
"""

serializer_class = LeavesWithProfilesSerializer
name = "search-node-with-profiles"

def get_queryset(self):
search_term = self.request.query_params.get("q", "")
if not search_term:
return TreeNode.objects.none()

if SERIALIZERS:
for profile_type in SERIALIZERS:

model_class = SERIALIZERS[profile_type].Meta.model
# Get the related query name from the model's TreeNode field
for field in model_class._meta.fields:
if (
isinstance(field, TreeForeignKey)
and field.remote_field.model == TreeNode
):
related_query_name = field.related_query_name()

return TreeNode.objects.filter(
Q(
**{
f"{related_query_name}__general_information__name__icontains": search_term,
f"{related_query_name}__general_information__synonyms__icontains": search_term,
}
)
).distinct()
return TreeNode.objects.none()

@action(detail=False, methods=["get"])
def search(self, request):
queryset = self.get_queryset()
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)


class ProfileSearchEndpoint(GenericViewSet):
"""
Endpoint that searches across all profile types and returns their native serialized data.
"""

name = "profile-search"

def get_queryset(self):
search_term = self.request.query_params.get("q", "")
if not search_term:
return []

results = []
if SERIALIZERS:
for profile_type in SERIALIZERS:
model = SERIALIZERS[profile_type].Meta.model
# This would be a way to include fields that are different for each profile type
# if (model._meta.model_name == "plant"):
# q_sub_name = Q(general_information__sub_name__icontains=search_term)
# else:
# q_sub_name = Q()
profile_results = model.objects.filter(
Q(general_information__name__icontains=search_term)
)
if profile_results.exists():
results.extend(profile_results)

return results

def get_serializer_class(self):
return SERIALIZERS.get(self.related_name, None)

def get_serializer_for_model(self, model_name):
for serializer_name, serializer_class in SERIALIZERS.items():
if serializer_class.Meta.model.__name__.lower() == model_name.lower():
return serializer_class
return None

@action(detail=False, methods=["get"])
def search(self, request):
queryset = self.get_queryset()
response_data = []
for item in queryset:
model_name = item._meta.model_name
serializer_class = self.get_serializer_for_model(model_name)
if serializer_class:
serializer = serializer_class(item, context={"request": request})
data = serializer.data
data["def_type"] = model_name
response_data.append(data)

return Response(response_data)