|
1 | 1 | import os
|
2 | 2 |
|
3 | 3 | from django.contrib import messages
|
4 |
| -from django.contrib.auth.models import User |
5 | 4 | from django.contrib.auth.decorators import login_required, user_passes_test
|
| 5 | +from django.contrib.auth.mixins import LoginRequiredMixin |
| 6 | +from django.contrib.auth.models import User |
6 | 7 | from django.db import transaction
|
7 | 8 | from django.http import HttpResponse
|
8 | 9 | from django.utils.encoding import force_str
|
|
15 | 16 |
|
16 | 17 | from . import forms
|
17 | 18 | from . import tasks
|
18 |
| -from .utils import contestadmin_auth |
| 19 | +from .utils import contestadmin_auth, ContestAdminAuthMixin |
19 | 20 | from contestadmin.models import Contest
|
20 | 21 | from contestsuite.settings import MEDIA_ROOT
|
21 | 22 | from lfg.models import LFGProfile
|
@@ -192,6 +193,53 @@ def get(self, request):
|
192 | 193 | return redirect('admin_dashboard')
|
193 | 194 |
|
194 | 195 |
|
| 196 | +class ExportTeamData(LoginRequiredMixin, ContestAdminAuthMixin, View): |
| 197 | + """ |
| 198 | + View which creates and serves a zip file containing contest team data per division. |
| 199 | + """ |
| 200 | + |
| 201 | + def get(self, request): |
| 202 | + """ |
| 203 | + Schedules generation of CSV files. |
| 204 | + """ |
| 205 | + |
| 206 | + tasks.generate_team_csvs.delay() |
| 207 | + messages.info(request, 'Team data CSVs generation scheduled.', fail_silently=True) |
| 208 | + |
| 209 | + return redirect('admin_dashboard') |
| 210 | + |
| 211 | + def download(self): |
| 212 | + """ |
| 213 | + Serves a ZIP file containing all team data CSV files. |
| 214 | + """ |
| 215 | + |
| 216 | + fpath = f"{MEDIA_ROOT}/team_files/" |
| 217 | + |
| 218 | + # Initialize zip file |
| 219 | + in_memory = BytesIO() |
| 220 | + zip = ZipFile(in_memory, 'a') |
| 221 | + |
| 222 | + # Add team csvs to zip file |
| 223 | + for fname in os.listdir(fpath): |
| 224 | + zip.write(fpath+fname, fname) |
| 225 | + |
| 226 | + # fix for Linux zip files read in Windows |
| 227 | + for file in zip.filelist: |
| 228 | + file.create_system = 0 |
| 229 | + |
| 230 | + zip.close() |
| 231 | + |
| 232 | + # Initialize response |
| 233 | + response = HttpResponse(content_type='application/zip') |
| 234 | + response['Content-Disposition'] = 'attachment; filename=team_data_csvs.zip' |
| 235 | + |
| 236 | + # Write zip file to response |
| 237 | + in_memory.seek(0) |
| 238 | + response.write(in_memory.read()) |
| 239 | + |
| 240 | + return response |
| 241 | + |
| 242 | + |
195 | 243 | @login_required
|
196 | 244 | @user_passes_test(contestadmin_auth, login_url='/', redirect_field_name=None)
|
197 | 245 | @transaction.atomic
|
@@ -324,6 +372,9 @@ def dashboard(request):
|
324 | 372 | context['dj_files_available'] = True
|
325 | 373 | else:
|
326 | 374 | context['dj_files_available'] = False
|
| 375 | + |
| 376 | + # Determine if team CSVs have been generated |
| 377 | + context['team_csvs_available'] = True if len(os.listdir(f"{MEDIA_ROOT}/team_files/")) > 0 else False |
327 | 378 |
|
328 | 379 | # Volunteer card data
|
329 | 380 | context['volunteers'] = [user for user in Profile.objects.order_by('role').all() if user.is_volunteer()]
|
|
0 commit comments