Skip to content
Snippets Groups Projects
Commit 31b18d0e authored by Nico Vermaas's avatar Nico Vermaas Committed by Mattia Mancini
Browse files

SDC-688 - develop the GUI

parent f1277708
No related branches found
No related tags found
1 merge request!12SDC-688 - develop the GUI
{% extends 'lofardata/../base.html' %} {% extends 'lofardata/base.html' %}
{% load static %} {% load static %}
......
from django.contrib.auth import views as auth_views
from django.urls import include, path from django.urls import include, path
from rest_framework.routers import DefaultRouter from django.contrib.auth import views as auth_views
from rest_framework.schemas import get_schema_view from rest_framework.schemas import get_schema_view
from rest_framework.routers import DefaultRouter
from . import views from . import views
router = DefaultRouter() router = DefaultRouter()
router.register(r'api/v1/workspecification', views.WorkSpecificationViewset, basename="workspecification") router.register(r'workspecification', views.WorkSpecificationViewset, basename="workspecification")
router.register(r'processing_site', views.ATDBProcessingSiteView, basename='processingsite')
urlpatterns = [ urlpatterns = [
# Workaround for injecting the urls from the ModelViewSet, which requires a "Router"
*router.urls,
# Perhaps both accounts and login could be moved to the ldv-spec main urls file? # Perhaps both accounts and login could be moved to the ldv-spec main urls file?
# authentication # authentication
path('accounts/', include('django.contrib.auth.urls')), path('accounts/', include('django.contrib.auth.urls')),
...@@ -31,6 +27,13 @@ urlpatterns = [ ...@@ -31,6 +27,13 @@ urlpatterns = [
description="API description", description="API description",
version="0.0.1" version="0.0.1"
), name='openapi-schema'), ), name='openapi-schema'),
path('api/v1/', include(router.urls)),
# GUI # GUI
path('', views.index, name='index'), path('', views.index, name='index'),
path('api/', views.api, name='api'),
path('specification/', views.specification_view, name='specification'),
path('specification/<int:pk>/', views.specification_view, name='specification-detail'),
# Workaround for injecting the urls from the ModelViewSet, which requires a "Router"
] ]
from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
from django.shortcuts import redirect
from django.shortcuts import render from django.shortcuts import render
from django.urls import reverse
from django_filters import rest_framework as filters from django_filters import rest_framework as filters
from rest_framework import generics, status, viewsets from rest_framework import generics, status, viewsets
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.schemas.openapi import AutoSchema from rest_framework.schemas.openapi import AutoSchema
from .models import ( from .forms import WorkSpecificationForm
ATDBProcessingSite, from .models import DataProduct, DataProductFilter, DataLocation, WorkSpecification, ATDBProcessingSite, DataFilterType
DataLocation, from .serializers import DataProductSerializer, \
DataProduct, DataProductFlatSerializer, DataLocationSerializer, \
DataProductFilter, WorkSpecificationSerializer, ATDBProcessingSiteSerializer
WorkSpecification,
)
from .serializers import (
DataLocationSerializer,
DataProductFlatSerializer,
DataProductSerializer,
WorkSpecificationSerializer,
)
from .tasks import insert_task_into_atdb from .tasks import insert_task_into_atdb
...@@ -33,7 +27,7 @@ class DynamicFilterSet(filters.FilterSet): ...@@ -33,7 +27,7 @@ class DynamicFilterSet(filters.FilterSet):
def _load_filters(self): def _load_filters(self):
if self.Meta.filter_class is None: if self.Meta.filter_class is None:
raise Exception("Define filter_class meta attribute") raise Exception('Define filter_class meta attribute')
for item in self.Meta.filter_class.objects.all(): for item in self.Meta.filter_class.objects.all():
field_obj = self.Meta.model._meta.get_field(item.field) field_obj = self.Meta.model._meta.get_field(item.field)
filter_class, *_ = self.filter_for_lookup(field_obj, item.lookup_type) filter_class, *_ = self.filter_for_lookup(field_obj, item.lookup_type)
...@@ -58,6 +52,82 @@ def index(request): ...@@ -58,6 +52,82 @@ def index(request):
return render(request, "lofardata/index.html", {"atdb_hosts": atdb_hosts}) return render(request, "lofardata/index.html", {"atdb_hosts": atdb_hosts})
def api(request):
atdb_hosts = ATDBProcessingSite.objects.values('name', 'url')
return render(request, "lofardata/api.html", {'atdb_hosts': atdb_hosts})
def construct_specifications_list():
results = ''
for specification in WorkSpecification.objects.all():
url = reverse('specification-detail', args=(str(specification.pk),))
line = f'<li><a class="dropdown-item" href="{url}">{str(specification)}</a></li>'
results += line
return results
def handle_specification_view_post(request, specification):
form = WorkSpecificationForm(request.POST, instance=specification)
if form.is_valid():
object_to_save = request.POST['save']
if object_to_save == 'save':
specification.async_task_result = None
specification.is_ready = False
specification.save()
return redirect('specification-detail', specification.pk)
elif object_to_save == 'save_and_send_to_atdb':
specification.save()
res = insert_task_into_atdb.delay(specification.pk)
return redirect('specification-detail', specification.pk)
elif object_to_save == 'save_and_add_successor':
specification.save()
successor = WorkSpecification()
successor.predecessor_specification = specification
successor.processing_site = specification.processing_site
successor.save()
return redirect('specification-detail', successor.pk)
def preprocess_filters_specification_view(specification):
dataproduct_filters = DataProductFilter.objects.all()
for dataproduct_filter in dataproduct_filters:
if specification.filters and dataproduct_filter.field in specification.filters:
dataproduct_filter.default = specification.filters[dataproduct_filter.field]
else:
dataproduct_filter.default = ''
if dataproduct_filter.filter_type == DataFilterType.DROPDOWN:
dataproduct_filter.choices = DataProduct.objects.distinct(dataproduct_filter.field).values_list(
dataproduct_filter.field)
return dataproduct_filters
def specification_view(request, pk=None):
try:
# retrieve existing specification
specification = WorkSpecification.objects.get(pk=pk)
except ObjectDoesNotExist:
# start new specification
specification = WorkSpecification()
specifications_list = construct_specifications_list()
# a POST means that the form is filled in and should be stored in the
form = WorkSpecificationForm(instance=specification)
if request.method == "POST":
return handle_specification_view_post(request, specification)
dataproduct_filters = preprocess_filters_specification_view(specification)
return render(request, "lofardata/specification.html", {
'form': form,
'specification': specification,
'specifications_list': specifications_list,
'filters': dataproduct_filters
})
# ---------- REST API views ---------- # ---------- REST API views ----------
class DataProductView(generics.ListCreateAPIView): class DataProductView(generics.ListCreateAPIView):
model = DataProduct model = DataProduct
...@@ -70,6 +140,13 @@ class DataProductView(generics.ListCreateAPIView): ...@@ -70,6 +140,13 @@ class DataProductView(generics.ListCreateAPIView):
filter_class = DataProductFilterSet filter_class = DataProductFilterSet
class ATDBProcessingSiteView(viewsets.ReadOnlyModelViewSet):
model = ATDBProcessingSite
serializer_class = ATDBProcessingSiteSerializer
queryset = ATDBProcessingSite.objects.all().order_by('pk')
class DataProductDetailsView(generics.RetrieveUpdateDestroyAPIView): class DataProductDetailsView(generics.RetrieveUpdateDestroyAPIView):
model = DataProduct model = DataProduct
serializer_class = DataProductSerializer serializer_class = DataProductSerializer
...@@ -116,11 +193,7 @@ class WorkSpecificationViewset(viewsets.ModelViewSet): ...@@ -116,11 +193,7 @@ class WorkSpecificationViewset(viewsets.ModelViewSet):
@action(detail=True, methods=["POST"]) @action(detail=True, methods=["POST"])
def submit(self, request, pk=None) -> Response: def submit(self, request, pk=None) -> Response:
# TODO: check that there are some matches in the request? # TODO: check that there are some matches in the request?
# TODO: how to specify the filter? # TODO: how to specify the filter?
res = insert_task_into_atdb.delay(pk) res = insert_task_into_atdb.delay(pk)
return Response({"detail": "accepted"}, status=status.HTTP_202_ACCEPTED) return Response({"detail": "accepted"}, status=status.HTTP_202_ACCEPTED)
python manage.py makemigrations --settings=ldvspec.settings.dev
python manage.py migrate --settings=ldvspec.settings.dev
...@@ -13,3 +13,5 @@ pyyaml==6.0 ...@@ -13,3 +13,5 @@ pyyaml==6.0
uritemplate==4.1.1 uritemplate==4.1.1
sshtunnel==0.4.0 sshtunnel==0.4.0
django-uws==0.2.dev355575 django-uws==0.2.dev355575
django-crispy-forms==1.14.0
crispy-bootstrap5==0.6
\ No newline at end of file
SET CELERY_BROKER_URL=amqp://guest@raspiastro:5672/
python manage.py runserver --settings=ldvspec.settings.dev
python manage.py test --settings=ldvspec.settings.dev
SET CELERY_BROKER_URL=amqp://guest@raspiastro:5672
celery -A ldvspec worker --pool=solo -l INFO
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment