import random from django.db import IntegrityError from django.http import HttpResponseNotFound, HttpResponseRedirect, JsonResponse, HttpResponseNotAllowed from django.shortcuts import render from django.contrib.auth import authenticate, login as auth_login, logout as auth_logout from django.contrib.auth.models import User from .forms import CreateEventForm, LoginForm, UpdateSlotsForm from .models import Event, Participant, Date from .helpers import slots2string, string2slots, get_slot_count, slots2grid def index(request): return render(request, 'zitap/index.html') def about(request): return render(request, 'zitap/about.html') def create_event(request): if request.method == 'POST': form = CreateEventForm(request.POST) if form.is_valid(): data = form.cleaned_data # Try to create the event. If the url is already taken, try again. n = 0 while n<10: try: event = Event.objects.create(name=data['event_name']) for date in data['event_date']: event.date_set.create(date=date) event.save() return HttpResponseRedirect(f'/{event.url}') except IntegrityError: n += 1 form.add_error(None, 'Could not create event. Please try again.') else: form = CreateEventForm() return render(request, 'zitap/create-event.html', {'form': form}) def event(request, url): try: event = Event.objects.get(url=url) except Event.DoesNotExist: return render(request, 'zitap/event-not-found.html') # Check if the user is logged in if 'participant_id' in request.session: participant = Participant.objects.get(id=request.session['participant_id']) login_form = None update_form = UpdateSlotsForm(initial={'slots': participant.slots}) else: login_form = LoginForm() update_form = None return render( request, 'zitap/event.html', {'event': event, 'grid': slots2grid(event), 'login_form': login_form, 'update_form': update_form} ) def login(request, url): try: event = Event.objects.get(url=url) except Event.DoesNotExist: return render(request, 'zitap/event-not-found.html') if request.method != 'POST': return HttpResponseNotAllowed(['POST']) form = LoginForm(request.POST) if form.is_valid(): data = form.cleaned_data user = authenticate(request, username=data['username'], password=data.get('password')) if user is None: try: user = User.objects.create_user(data['username'], password=data.get('password')) except IntegrityError: form.add_error('username', 'Username already exists') return render( request, 'zitap/event.html', {'event': event, 'grid': slots2grid(event), 'login_form': form, 'update_form': None} ) auth_login(request, user) participant, created = Participant.objects.get_or_create(event=event, user=user) participant.slots = random.getrandbits(get_slot_count(event)).to_bytes(get_slot_count(event) // 8, 'big') participant.save() request.session['participant_id'] = participant.id return HttpResponseRedirect(f'/{event.url}') def logout(request, url): try: event = Event.objects.get(url=url) except Event.DoesNotExist: return render(request, 'zitap/event-not-found.html') if 'participant_id' in request.session: del request.session['participant_id'] return HttpResponseRedirect(f'/{event.url}') def update_slots(request, url): try: event = Event.objects.get(url=url) except Event.DoesNotExist: return render(request, 'zitap/event-not-found.html') if request.method != 'POST': return HttpResponseNotAllowed(['POST']) form = UpdateSlotsForm(request.POST) if form.is_valid(): data = form.cleaned_data participant = Participant.objects.get(id=request.session['participant_id']) participant.slots = string2slots(data['slots']) participant.save() return HttpResponseRedirect(f'/{event.url}') def slots_api(request, url): """ REST JSON API for slots of all participants of an event Slots are represented as a string of 0s and 1s where 0 means the slot is available and 1 means the slot is taken. The string begins with the first slot of the first day of the event and ends with the last slot of the last day of the event. """ try: event = Event.objects.get(url=url) slot_count = get_slot_count(event) # Check if the user is logged in and wants to update their slots if 'participant_id' in request.session and request.method == 'POST': participant = Participant.objects.get(id=request.session['participant_id']) form = UpdateSlotsForm(request.POST) if form.is_valid(): data = form.cleaned_data participant.slots = string2slots(data['slots']) participant.save() # Get the slots of each participant data = {} participants = event.participant_set.all() for participant in participants: data[participant.name] = slots2string(participant, slot_count) return JsonResponse(data) except Event.DoesNotExist: return HttpResponseNotFound()