diff --git a/tournaments/templates/tournaments/admin/tournament_cleaner.html b/tournaments/templates/tournaments/admin/tournament_cleaner.html
new file mode 100644
index 0000000..ed3aa68
--- /dev/null
+++ b/tournaments/templates/tournaments/admin/tournament_cleaner.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Tournament Import
+
+
+
+
+
diff --git a/tournaments/urls.py b/tournaments/urls.py
index e4b316b..5670262 100644
--- a/tournaments/urls.py
+++ b/tournaments/urls.py
@@ -38,4 +38,5 @@ urlpatterns = [
path('terms-of-use/', views.terms_of_use, name='terms-of-use'),
path('utils/xls-to-csv/', views.xls_to_csv, name='xls-to-csv'),
path('mail-test/', views.simple_form_view, name='mail-test'),
+ path('admin/tournament-import/', views.tournament_import_view, name='tournament_import'),
]
diff --git a/tournaments/views.py b/tournaments/views.py
index e30e420..b088cdd 100644
--- a/tournaments/views.py
+++ b/tournaments/views.py
@@ -5,6 +5,7 @@ from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.urls import reverse
from django.views.decorators.csrf import csrf_exempt
+from django.contrib.admin.views.decorators import staff_member_required
from django.core.files.storage import default_storage
from django.core.files.base import ContentFile
@@ -22,6 +23,7 @@ from django.db.models import Q
import json
import asyncio
import csv
+import zipfile
from api.tokens import account_activation_token
@@ -483,3 +485,94 @@ def send_email(mail, name):
email = EmailMessage(subject, body, to=[mail])
email.send()
+
+from api.serializers import GroupStageSerializer, MatchSerializer, PlayerRegistrationSerializer, RoundSerializer, TeamRegistrationSerializer, TeamScoreSerializer
+
+@staff_member_required
+def tournament_import_view(request):
+ if request.method == 'POST':
+ zip_file = request.FILES.get('tournament_zip')
+ if zip_file:
+ try:
+ tournament_id = os.path.splitext(zip_file.name)[0]
+ tournament = Tournament.objects.get(id=tournament_id)
+
+ # Delete existing relationships
+ tournament.round_set.all().delete()
+ tournament.groupstage_set.all().delete()
+ tournament.teamregistration_set.all().delete()
+
+ with zipfile.ZipFile(zip_file) as z:
+ # First, process rounds
+ rounds_data = get_file_data(z, f"{tournament_id}/rounds.json")
+ if rounds_data:
+ # First pass: Create rounds without parent relationships
+ rounds_without_parent = []
+ for item in rounds_data:
+ item['tournament'] = tournament.id
+ # Temporarily remove parent field
+ parent = item.pop('parent', None)
+ rounds_without_parent.append({'data': item, 'parent': parent})
+
+ serializer = RoundSerializer(data=[item['data'] for item in rounds_without_parent], many=True)
+ serializer.is_valid(raise_exception=True)
+ created_rounds = serializer.save()
+
+ # Create a mapping of round IDs
+ round_mapping = {round_obj.id: round_obj for round_obj in created_rounds}
+
+ # Second pass: Update parent relationships
+ for round_obj, original_data in zip(created_rounds, rounds_without_parent):
+ if original_data['parent']:
+ round_obj.parent = round_mapping.get(original_data['parent'])
+ round_obj.save()
+
+ # Then process all other files
+ serializer_mapping = {
+ 'group-stages.json': GroupStageSerializer,
+ 'team-registrations.json': TeamRegistrationSerializer,
+ 'matches.json': MatchSerializer,
+ 'player-registrations.json': PlayerRegistrationSerializer,
+ 'team-scores.json': TeamScoreSerializer
+ }
+
+ # Process each remaining file
+ for filename, serializer_class in serializer_mapping.items():
+ process_file(z, filename, tournament_id, tournament, serializer_class)
+
+ return JsonResponse({'status': 'success'})
+
+ except Exception as e:
+ return JsonResponse({'status': 'error', 'message': str(e)})
+ else:
+ return render(request, 'tournaments/admin/tournament_cleaner.html')
+
+def process_file(zip_file, filename, tournament_id, tournament, serializer_class):
+ """Helper function to process individual files"""
+ try:
+ file_path = f"{tournament_id}/{filename}"
+ json_data = get_file_data(zip_file, file_path)
+
+ if json_data:
+ # Add tournament to each item
+ for item in json_data:
+ item['tournament'] = tournament.id
+
+ serializer = serializer_class(data=json_data, many=True)
+ serializer.is_valid(raise_exception=True)
+ serializer.save()
+
+ except Exception as e:
+ print(f"Error processing {filename}: {str(e)}")
+
+def get_file_data(zip_file, file_path):
+ """Helper function to read and parse JSON data from zip file"""
+ try:
+ file_content = zip_file.read(file_path)
+ return json.loads(file_content)
+ except KeyError:
+ print(f"File not found: {file_path}")
+ return None
+ except json.JSONDecodeError as e:
+ print(f"JSON Error for {file_path}: {str(e)}")
+ raise Exception(f"Invalid JSON in file {file_path}")