diff --git a/README.md b/README.md index 8c6da464e..c35898589 100644 --- a/README.md +++ b/README.md @@ -20,10 +20,10 @@ If you wish to configure your own instance of Codabench platform, here are the i ``` $ cp .env_sample .env -$ docker-compose up -d -$ docker-compose exec django ./manage.py migrate -$ docker-compose exec django ./manage.py generate_data -$ docker-compose exec django ./manage.py collectstatic --noinput +$ docker compose up -d +$ docker compose exec django ./manage.py migrate +$ docker compose exec django ./manage.py generate_data +$ docker compose exec django ./manage.py collectstatic --noinput ``` You can now login as username "admin" with password "admin" at http://localhost/ diff --git a/src/apps/api/views/submissions.py b/src/apps/api/views/submissions.py index 745cdb521..6c2489245 100644 --- a/src/apps/api/views/submissions.py +++ b/src/apps/api/views/submissions.py @@ -312,18 +312,18 @@ def re_run_many_submissions(self, request): submission.re_run() return Response({}) - # New methods impleted! @action(detail=False, methods=['get']) def download_many(self, request): pks = request.query_params.get('pks') if pks: pks = json.loads(pks) # Convert JSON string to list + # Doing a local import here to avoid circular imports from competitions.tasks import stream_batch_download - # Call the task and get the result (stream) + # in_memory_zip = stream_batch_download.apply_async((pks,)).get() in_memory_zip = stream_batch_download(pks) - # Stream the response + response = StreamingHttpResponse(in_memory_zip, content_type='application/zip') response['Content-Disposition'] = 'attachment; filename="bulk_submissions.zip"' return response diff --git a/src/apps/api/views/tasks.py b/src/apps/api/views/tasks.py index 2c1642448..71bfb59bd 100644 --- a/src/apps/api/views/tasks.py +++ b/src/apps/api/views/tasks.py @@ -84,9 +84,26 @@ def get_serializer_context(self): return context def update(self, request, *args, **kwargs): + + # Get task task = self.get_object() + + # Raise error if user is not the creator of the task or not a super user if request.user != task.created_by and not request.user.is_superuser: raise PermissionDenied("Cannot update a task that is not yours") + + # If the key is not in the request data, set the corresponding field to None + # No condition for scoring program because a task must have a scoring program + if "ingestion_program" not in request.data: + task.ingestion_program = None + if "input_data" not in request.data: + task.input_data = None + if "reference_data" not in request.data: + task.reference_data = None + + # Save the task to apply the changes + task.save() + return super().update(request, *args, **kwargs) def destroy(self, request, *args, **kwargs): diff --git a/src/apps/competitions/tasks.py b/src/apps/competitions/tasks.py index 1e5544b7b..f56696940 100644 --- a/src/apps/competitions/tasks.py +++ b/src/apps/competitions/tasks.py @@ -292,13 +292,10 @@ def retrieve_data(url, data=None): def zip_generator(submission_pks): in_memory_zip = BytesIO() - # logger.info("IN zip generator") with zipfile.ZipFile(in_memory_zip, 'w', zipfile.ZIP_DEFLATED) as zip_file: for submission_id in submission_pks: submission = Submission.objects.get(id=submission_id) - # logger.info(submission.data.data_file) - - short_name = submission.data.data_file.name.split('/')[-1] + short_name = "ID_" + str(submission_id) + '_' + submission.data.data_file.name.split('/')[-1] url = make_url_sassy(path=submission.data.data_file.name) for block in retrieve_data(url): zip_file.writestr(short_name, block) @@ -310,8 +307,6 @@ def zip_generator(submission_pks): @app.task(queue='site-worker', soft_time_limit=60 * 60) def stream_batch_download(submission_pks): - # logger.info("In stream_batch_download") - # logger.info(submission_pks) return zip_generator(submission_pks) diff --git a/src/apps/pages/urls.py b/src/apps/pages/urls.py index 084bd2c7e..bbba17d71 100644 --- a/src/apps/pages/urls.py +++ b/src/apps/pages/urls.py @@ -11,5 +11,6 @@ path('search', views.SearchView.as_view(), name="search"), path('organize', views.OrganizeView.as_view(), name="organize"), path('server_status', views.ServerStatusView.as_view(), name="server_status"), + path('monitor_queues', views.MonitorQueuesView.as_view(), name="monitor_queues"), # path('test', views.CompetitionListTestView.as_view()), ] diff --git a/src/apps/pages/views.py b/src/apps/pages/views.py index 4afa0c11d..0f21b8cf2 100644 --- a/src/apps/pages/views.py +++ b/src/apps/pages/views.py @@ -1,5 +1,4 @@ -from datetime import timedelta -from django.utils.timezone import now +from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage from django.views.generic import TemplateView from django.db.models import Count, Q @@ -55,6 +54,8 @@ class ServerStatusView(TemplateView): def get_context_data(self, *args, **kwargs): show_child_submissions = self.request.GET.get('show_child_submissions', False) + page = self.request.GET.get('page', 1) + submissions_per_page = 50 # Get all submissions qs = Submission.objects.all() @@ -73,9 +74,6 @@ def get_context_data(self, *args, **kwargs): else: qs = qs.none() # This returns an empty queryset - # Filter for fetching last 2 days submissions - qs = qs.filter(created_when__gte=now() - timedelta(days=2)) - # Filter out child submissions i.e. submission has no parent if not show_child_submissions: qs = qs.filter(parent__isnull=True) @@ -83,8 +81,20 @@ def get_context_data(self, *args, **kwargs): qs = qs.order_by('-created_when') qs = qs.select_related('phase__competition', 'owner') + # Paginate the queryset + paginator = Paginator(qs, submissions_per_page) + + try: + submissions = paginator.page(page) + except PageNotAnInteger: + # If page is not an integer, deliver the first page. + submissions = paginator.page(1) + except EmptyPage: + # If page is out of range, deliver last page of results. + submissions = paginator.page(paginator.num_pages) + context = super().get_context_data(*args, **kwargs) - context['submissions'] = qs[:250] + context['submissions'] = submissions context['show_child_submissions'] = show_child_submissions for submission in context['submissions']: @@ -103,6 +113,9 @@ def get_context_data(self, *args, **kwargs): # Add submission owner display name submission.owner_display_name = submission.owner.display_name if submission.owner.display_name else submission.owner.username + context['paginator'] = paginator + context['is_paginated'] = paginator.num_pages > 1 + return context def format_file_size(self, file_size): @@ -123,6 +136,10 @@ def format_file_size(self, file_size): return f"{n:.1f} {units[i]}" +class MonitorQueuesView(TemplateView): + template_name = 'pages/monitor_queues.html' + + def page_not_found_view(request, exception): print(request) return render(request, '404.html', status=404) diff --git a/src/static/riot/tasks/management.tag b/src/static/riot/tasks/management.tag index 78c0f793d..37510275e 100644 --- a/src/static/riot/tasks/management.tag +++ b/src/static/riot/tasks/management.tag @@ -274,7 +274,7 @@
Thanks,
Codabench Team
+