Page MenuHomeSoftware Heritage
Paste P1323

[POC] Deposit private API endpoint for datatables to list deposits
ActivePublic

Authored by anlambert on Mar 30 2022, 6:03 PM.
diff --git a/swh/deposit/api/private/deposit_list.py b/swh/deposit/api/private/deposit_list.py
index 4bb40e31..e8c07e31 100644
--- a/swh/deposit/api/private/deposit_list.py
+++ b/swh/deposit/api/private/deposit_list.py
@@ -3,10 +3,20 @@
# License: GNU General Public License version 3, or any later version
# See top-level LICENSE file for more information
-
+from django.core.paginator import Paginator
+from django.db.models import CharField, Q, TextField
+from django.http import JsonResponse
+from rest_framework.decorators import (
+ api_view,
+ authentication_classes,
+ permission_classes,
+)
from rest_framework.generics import ListAPIView
+from rest_framework.permissions import AllowAny
+import sentry_sdk
from swh.deposit.api.utils import DefaultPagination, DepositSerializer
+from swh.deposit.utils import parse_swh_deposit_origin, parse_swh_metadata_provenance
from . import APIPrivateView
from ...models import Deposit
@@ -66,3 +76,96 @@ class APIList(ListAPIView, APIPrivateView):
deposits_qs = deposits_qs.exclude(external_id__startswith=exclude_like)
return deposits_qs.order_by("id")
+
+
+def _deposit_search_query(search_value: str) -> Q:
+ fields = [f for f in Deposit._meta.fields if isinstance(f, (CharField, TextField))]
+ queries = [Q(**{f.name + "__icontains": search_value}) for f in fields]
+ search_query = Q()
+ for query in queries:
+ search_query = search_query | query
+ return search_query
+
+
+@api_view()
+@authentication_classes([])
+@permission_classes([AllowAny])
+def deposit_list_datatables(request):
+ table_data = {}
+ table_data["draw"] = int(request.GET["draw"])
+ try:
+ deposits = Deposit.objects.all()
+ deposits_count = deposits.count()
+ search_value = request.GET["search[value]"]
+ if search_value:
+ deposits = deposits.filter(_deposit_search_query(search_value))
+
+ exclude_pattern = request.GET.get("excludePattern")
+ if exclude_pattern:
+ deposits = deposits.exclude(_deposit_search_query(exclude_pattern))
+
+ column_order = request.GET["order[0][column]"]
+ field_order = request.GET["columns[%s][name]" % column_order]
+ order_dir = request.GET["order[0][dir]"]
+
+ if order_dir == "desc":
+ field_order = "-" + field_order
+
+ deposits = deposits.order_by(field_order)
+
+ length = int(request.GET["length"])
+ page = int(request.GET["start"]) / length + 1
+ paginator = Paginator(deposits, length)
+
+ data = [DepositSerializer(d).data for d in paginator.page(page).object_list]
+
+ table_data["recordsTotal"] = deposits_count
+ table_data["recordsFiltered"] = deposits.count()
+ data_list = []
+ for d in data:
+ data_dict = {
+ "id": d["id"],
+ "type": d["type"],
+ "external_id": d["external_id"],
+ "reception_date": d["reception_date"],
+ "status": d["status"],
+ "status_detail": d["status_detail"],
+ "swhid": d["swhid"],
+ "swhid_context": d["swhid_context"],
+ }
+ provenance = None
+ raw_metadata = d["raw_metadata"]
+ # Try to determine provenance out of the raw metadata
+ if raw_metadata and d["type"] == "meta": # metadata provenance
+ provenance = parse_swh_metadata_provenance(d["raw_metadata"])
+ elif raw_metadata and d["type"] == "code":
+ provenance = parse_swh_deposit_origin(raw_metadata)
+
+ if not provenance and d["origin_url"]:
+ provenance = d["origin_url"]
+
+ # Finally, if still not found, we determine uri using the swhid
+ if not provenance and d["swhid_context"]:
+ # Trying to compute the origin as we did before in the js
+ from swh.model.swhids import QualifiedSWHID
+
+ swhid = QualifiedSWHID.from_string(d["swhid_context"])
+ provenance = swhid.origin
+
+ data_dict["uri"] = provenance # could be None
+
+ # This could be large. As this is not displayed yet, drop it to avoid
+ # cluttering the data dict
+ data_dict.pop("raw_metadata", None)
+
+ data_list.append(data_dict)
+
+ table_data["data"] = data_list
+
+ except Exception as exc:
+ sentry_sdk.capture_exception(exc)
+ table_data[
+ "error"
+ ] = "An error occurred while retrieving the list of deposits !"
+
+ return JsonResponse(table_data)
diff --git a/swh/deposit/api/private/urls.py b/swh/deposit/api/private/urls.py
index e48290d6..2243aca1 100644
--- a/swh/deposit/api/private/urls.py
+++ b/swh/deposit/api/private/urls.py
@@ -10,10 +10,11 @@ from ...config import (
PRIVATE_GET_DEPOSIT_METADATA,
PRIVATE_GET_RAW_CONTENT,
PRIVATE_LIST_DEPOSITS,
+ PRIVATE_LIST_DEPOSITS_DATATABLES,
PRIVATE_PUT_DEPOSIT,
)
from .deposit_check import APIChecks
-from .deposit_list import APIList
+from .deposit_list import APIList, deposit_list_datatables
from .deposit_read import APIReadArchives, APIReadMetadata
from .deposit_update_status import APIUpdateStatus
@@ -75,4 +76,9 @@ urlpatterns = [
name=PRIVATE_CHECK_DEPOSIT + "-nc",
),
url(r"^deposits/$", APIList.as_view(), name=PRIVATE_LIST_DEPOSITS),
+ url(
+ r"^deposits/datatables/$",
+ deposit_list_datatables,
+ name=PRIVATE_LIST_DEPOSITS_DATATABLES,
+ ),
]
diff --git a/swh/deposit/config.py b/swh/deposit/config.py
index 758ecf09..e91a781b 100644
--- a/swh/deposit/config.py
+++ b/swh/deposit/config.py
@@ -27,6 +27,7 @@ PRIVATE_CHECK_DEPOSIT = "check-deposit"
PRIVATE_PUT_DEPOSIT = "private-update"
PRIVATE_GET_DEPOSIT_METADATA = "private-read"
PRIVATE_LIST_DEPOSITS = "private-deposit-list"
+PRIVATE_LIST_DEPOSITS_DATATABLES = "private-deposit-list-datatables"
ARCHIVE_KEY = "archive"
RAW_METADATA_KEY = "raw-metadata"