Newer
Older
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.exceptions import ObjectDoesNotExist
from django.http import HttpResponseRedirect
from django.shortcuts import redirect, render

Fanna Lautenbach
committed
from django.views.generic import DeleteView, DetailView, UpdateView, TemplateView

Fanna Lautenbach
committed
from rest_framework import generics, viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.schemas.openapi import AutoSchema
from .forms import WorkSpecificationForm, GroupForm
from .mixins import CanAccessWorkSpecificationMixin
from .models import (
ATDBProcessingSite,
DataProduct,
DataProductFilter,
WorkSpecification,
)
from .serializers import (
ATDBProcessingSiteSerializer,
DataProductFlatSerializer,
DataProductSerializer,
WorkSpecificationSerializer,
)
from .tasks import insert_task_into_atdb

Fanna Lautenbach
committed
from .view_helpers import inputs_processor, dataproductinfo, filters_preprocessor
from .view_helpers.specification import set_post_submit_values, split_obs_ids_string, \
create_work_specifications_for_group
filter_class = None
def __init__(self, *args, **kwargs):
self._load_filters()
super().__init__(*args, **kwargs)
def _load_filters(self):
if self.Meta.filter_class is None:
for item in self.Meta.filter_class.objects.all():
field_obj = self.Meta.model._meta.get_field(item.field)
filter_class, *_ = self.filter_for_lookup(field_obj, item.lookup_type)
self.base_filters[item.name] = filter_class(item.field)
# --- Filters ---
class DataProductFilterSet(DynamicFilterSet):
class Meta:
model = DataProduct
filter_class = DataProductFilter
# ---------- GUI Views -----------
atdb_hosts = ATDBProcessingSite.objects.values("name", "url")
return render(request, "lofardata/api.html", {"atdb_hosts": atdb_hosts})
class Specifications(ListView):
serializer_class = WorkSpecificationSerializer
template_name = "lofardata/index.html"
model = WorkSpecification
ordering = ["-created_on"]
def get_queryset(self):
queryset = WorkSpecification.objects.all()
current_user: User = self.request.user
if current_user.is_staff or current_user.is_superuser:
return queryset.order_by("-created_on")
return queryset.filter(created_by=current_user.id).order_by("-created_on")
class WorkSpecificationCreateUpdateView(LoginRequiredMixin, CanAccessWorkSpecificationMixin, UpdateView):
template_name = "lofardata/workspecification/create_update.html"
model = WorkSpecification
form_class = WorkSpecificationForm
def get(self, request, *args, **kwargs):
specification = self.get_object()
if specification.is_editable():
return super().get(request, *args, **kwargs)
else:
return redirect('specification-detail', self.kwargs["pk"])
def get_object(self, queryset=None):
if self.kwargs.__len__() == 0 or self.kwargs["pk"] is None:
specification = WorkSpecification()
else:
specification = WorkSpecification.objects.get(pk=self.kwargs["pk"])
return specification
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
try:
specification = WorkSpecification.objects.get(pk=context["object"].pk)
except ObjectDoesNotExist:
specification = None

Fanna Lautenbach
committed
context["filters"] = filters_preprocessor.preprocess(specification)
context["processing_sites"] = list(ATDBProcessingSite.objects.values("name", "url"))
return context
def create_successor(self, specification):
successor = WorkSpecification()
successor.predecessor_specification = specification
successor.processing_site = specification.processing_site
successor.save()
return self.get_success_url(pk=successor.pk)
def form_valid(self, form):
action_ = form.data["action"]
specification = form.instance
if action_ == "Submit":
set_post_submit_values(specification, self.request.user)
if action_ == "Send":
insert_task_into_atdb.delay(specification.pk)
if action_ == "Successor":
specification.save()
successor = WorkSpecification()
successor.predecessor_specification = specification
successor.processing_site = specification.processing_site
successor.selected_workflow = specification.selected_workflow
return HttpResponseRedirect(self.create_successor(specification))
def get_success_url(self, **kwargs):
if kwargs.__len__() == 0 or kwargs["pk"] is None:
return reverse_lazy("index")
return reverse_lazy("specification-update", kwargs={"pk": kwargs["pk"]})
class WorkSpecificationDetailView(LoginRequiredMixin, CanAccessWorkSpecificationMixin, DetailView):
template_name = "lofardata/workspecification/detail.html"
model = WorkSpecification
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
specification = WorkSpecification.objects.get(pk=context["object"].pk)

Fanna Lautenbach
committed
context["filters"] = filters_preprocessor.preprocess(specification)
total_input_size, number_of_files, average_file_size = inputs_processor.compute_size_of_inputs(
specification.inputs
)
context["number_of_files"] = number_of_files

Fanna Lautenbach
committed
context["total_input_size"] = inputs_processor.format_size(total_input_size)
context["size_per_task"] = inputs_processor.format_size(
average_file_size * specification.batch_size
if specification.batch_size > 0
else total_input_size
)
return context
class WorkSpecificationDeleteView(LoginRequiredMixin, CanAccessWorkSpecificationMixin, DeleteView):
template_name = "lofardata/workspecification/delete.html"
model = WorkSpecification
success_url = reverse_lazy("index")
class WorkSpecificationInputsView(LoginRequiredMixin, CanAccessWorkSpecificationMixin, DetailView):
template_name = "lofardata/workspecification/inputs.html"
model = WorkSpecification
class WorkSpecificationATDBTasksView(LoginRequiredMixin, CanAccessWorkSpecificationMixin, DetailView):
template_name = "lofardata/workspecification/tasks.html"
model = WorkSpecification
class WorkSpecificationDatasetSizeInfoView(LoginRequiredMixin, CanAccessWorkSpecificationMixin, DetailView):
template_name = "lofardata/workspecification/dataset_size_info.html"
model = WorkSpecification
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
specification = WorkSpecification.objects.get(pk=context["object"].pk)

Fanna Lautenbach
committed
min_size, max_size, n_bins, counts, biggest_bucket, bins = inputs_processor.compute_inputs_histogram(
specification.inputs)

Fanna Lautenbach
committed
context["min_size"] = inputs_processor.format_size(min_size)
context["max_size"] = inputs_processor.format_size(max_size)
context["biggest_bucket"] = biggest_bucket
context["n_bins"] = n_bins
context["counts"] = counts
context["bins"] = bins
return context
class DataProductViewPerSasID(LoginRequiredMixin, CanAccessWorkSpecificationMixin, TemplateView):
template_name = "lofardata/workspecification/dataproducts.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
try:
specification = self.get_object()
except ObjectDoesNotExist:
return context
sas_id = specification.filters['obs_id']
context["sas_id"] = sas_id

Fanna Lautenbach
committed
context["dataproduct_info"] = dataproductinfo.retrieve_combined_information(sas_id)
def get_object(self):
return WorkSpecification.objects.get(pk=self.kwargs['pk'])
# ---------- REST API views ----------
class DataProductView(generics.ListCreateAPIView):
model = DataProduct
serializer_class = DataProductSerializer
queryset = DataProduct.objects.all().order_by("obs_id")
# using the Django Filter Backend - https://django-filter.readthedocs.io/en/latest/index.html
filter_backends = (filters.DjangoFilterBackend,)
class ATDBProcessingSiteView(viewsets.ReadOnlyModelViewSet):
model = ATDBProcessingSite
serializer_class = ATDBProcessingSiteSerializer
queryset = ATDBProcessingSite.objects.all().order_by("pk")

Roy de Goei
committed
class DataProductDetailsView(generics.RetrieveUpdateDestroyAPIView):
model = DataProduct
serializer_class = DataProductSerializer
queryset = DataProduct.objects.all()
class InsertWorkSpecificationSchema(AutoSchema):
def get_operation_id_base(self, path, method, action):
class InsertMultiDataproductView(generics.CreateAPIView):
"""
Add single DataProduct
"""
queryset = DataProduct.objects.all()
serializer_class = DataProductFlatSerializer
"""if an array is passed, set serializer to many"""
if isinstance(kwargs.get("data", {}), list):
kwargs["many"] = True
class WorkSpecificationViewset(viewsets.ModelViewSet):
queryset = WorkSpecification.objects.all()
serializer_class = WorkSpecificationSerializer
def get_queryset(self):
current_user: User = self.request.user
if not current_user.is_staff or not current_user.is_superuser:
return self.queryset.filter(created_by=current_user.id)
@action(detail=True, methods=["POST"])
def submit(self, request, pk=None) -> Response:
# TODO: check that there are some matches in the request?
class GroupCreateUpdateView(LoginRequiredMixin, UpdateView):
template_name = "lofardata/group/create_update.html"
model = Group
form_class = GroupForm
def get_object(self, queryset=None):
if self.kwargs.__len__() == 0 or self.kwargs["pk"] is None:
group = Group()
else:
group = Group.objects.get(pk=self.kwargs["pk"])
return group
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["processing_sites"] = list(ATDBProcessingSite.objects.values("name", "url"))
return context
def form_valid(self, form):
group = form.save()
obs_ids = split_obs_ids_string(form.data.get("obs_ids"))
create_work_specifications_for_group(group, self.request.user, obs_ids)
return super().form_valid(form)
def get_success_url(self, **kwargs):
return reverse_lazy("index")