This repository has been archived on 2022-08-01. You can view files and clone it, but cannot push or open issues or pull requests.
DEMOS2/allauthdemo/polls/utils/CreateNewEventModelAdaptor.py

220 lines
8 KiB
Python

from datetime import datetime
from django.utils.dateparse import parse_datetime
from allauthdemo.polls.models import Event
from allauthdemo.polls.models import Poll
from allauthdemo.polls.models import PollOption
from allauthdemo.polls.models import EmailUser
from allauthdemo.auth.models import DemoUser
'''
Goal: Convert the new form data (from the updated DEMOS2 UI) returned to '/event/create' into
an Event object that can be persisted via a Model to the DB
Author: Vincent de Almeida
Created: 11/07/2018
'''
# TODO: Define a validation function that can do back-end verification on top of the front end validation
# TODO: Validation can make use of __contains__ from QueryDict:
# TODO: https://docs.djangoproject.com/en/2.0/ref/request-response/#django.http.QueryDict
class CreateNewEventModelAdaptor:
# Raw data from form and django
form_data = None
user = None
# Extracted form data
event_name = None
identifier = None
starts_at = None
ends_at = None
min_num_selections = 0
max_num_selections = 0
organisers = []
trustees = []
voters = []
# Each element of the map has a sub array with 2 elements - poll and associated options
polls_options_map = []
# Event Model Object containing all the extracted data
event = None
def __init__(self, form_data, user):
self.form_data = form_data.copy()
self.user = user
# TODO: Call validation func here (incl functionality for verifying CSRF + reCAPTCHA)
self.__extractData()
def __extractData(self):
# Extract name and identifier first
self.event_name = self.form_data.pop('name-input')[0]
self.identifier = self.form_data.pop('identifier-input')[0]
# Extract start and end times as string and convert to datetime
# The UTC offset comes with a colon i.e. '+01:00' which needs to be removed
starts_at = self.form_data.pop('vote-start-input')[0]
starts_at_offset_index = starts_at.find('+')
if starts_at_offset_index != -1:
starts_at_time = starts_at[0: starts_at_offset_index-1].replace(' ', 'T')
starts_at_offset = starts_at[starts_at_offset_index:].replace(':', '')
starts_at = starts_at_time + starts_at_offset
self.starts_at = parse_datetime(starts_at)
else:
self.starts_at = datetime.strptime(starts_at, '%Y-%m-%d %H:%M')
ends_at = self.form_data.pop('vote-end-input')[0]
ends_at_offset_index = ends_at.find('+')
if ends_at_offset_index != -1:
ends_at_time = ends_at[0:ends_at_offset_index-1].replace(' ', 'T')
ends_at_offset = ends_at[ends_at_offset_index:].replace(':', '')
ends_at = ends_at_time + ends_at_offset
self.ends_at = parse_datetime(ends_at)
else:
self.ends_at = datetime.strptime(ends_at, '%Y-%m-%d %H:%M')
# Extract the list of organisers
organisers_list = self.form_data.pop('organiser-email-input')
for organiser in organisers_list:
if organiser != '' and DemoUser.objects.filter(email=organiser).count() == 1:
self.organisers.append(DemoUser.objects.filter(email=organiser).get())
# Extract the list of trustees
trustees_list = self.form_data.pop('trustee-email-input')
for trustee in trustees_list:
if trustee != '':
if EmailUser.objects.filter(email=trustee).count() == 1:
self.trustees.append(EmailUser.objects.filter(email=trustee).get())
else:
self.trustees.append(EmailUser(email=trustee))
# Extract the email list of voters
voters_csv_string = self.form_data.pop('voters-list-input')[0].replace(' ', '')
voters_email_list = voters_csv_string.split(',')
for voter_email in voters_email_list:
if voter_email != '':
if EmailUser.objects.filter(email=voter_email).count() == 1:
self.voters.append(EmailUser.objects.filter(email=voter_email).get())
else:
self.voters.append(EmailUser(email=voter_email))
# Extract the min and max number of selections
self.min_num_selections = int(self.form_data.pop('minimum-input')[0])
self.max_num_selections = int(self.form_data.pop('maximum-input')[0])
# Create the Event model object - this does not persist it to the DB
self.event = Event(start_time=self.starts_at,
end_time=self.ends_at,
title=self.event_name,
EID=self.identifier,
creator=self.user.first_name + ' ' + self.user.last_name,
c_email=self.user.email,
trustees=voters_csv_string)
def __gen_polls_options_map(self):
# At the time of writing, you can only define one poll at event-creation time
# Generate PollOption objects from the option data defined in form_data
options = self.form_data.pop('option-name-input')
poll_options_list = []
for option in options:
if option != '':
poll_options_list.append(PollOption(choice_text=option, votes=0))
# Extract required Poll object data and create a poll with its PollOption objects
text = self.form_data.pop('question-input')[0]
votes = 0
poll = Poll(question_text=text,
total_votes=votes,
min_num_selections=self.min_num_selections,
max_num_selections=self.max_num_selections,
event=self.event)
self.polls_options_map.append([poll, poll_options_list])
# Instantiate all the polls and their associated poll options
def __get_instantiated_polls(self):
polls = []
for poll_option_map in self.polls_options_map:
poll = poll_option_map[0]
poll_options = poll_option_map[1]
# Save the poll to the db
poll.save()
# Instantiate poll options
for option in poll_options:
option.question = poll
option.save()
poll.options = poll_options
poll.save()
polls.append(poll)
return polls
def updateModel(self):
# First thing to do is persist the event object to the db
# with basic data before adding things like poll data
self.event.save()
# List of organisers should already be instantiated and present in the db
# so it can just be added
self.event.users_organisers = self.organisers
# Add the list of trustees to the event, making sure they're instantiated
for trustee in self.trustees:
if EmailUser.objects.filter(email=trustee.email).count() == 0:
trustee.save()
self.event.users_trustees = self.trustees
# Add the list of voters to the event, making sure they're instantiated
for voter in self.voters:
if EmailUser.objects.filter(email=voter.email).count() == 0:
voter.save()
self.event.voters = self.voters
# Extract all the poll data for the event and associated poll option data
# This can only be done at this point as the event has been persisted
self.__gen_polls_options_map()
# Get the instantiated list of polls which have already instantiated options
self.event.polls = self.__get_instantiated_polls()
self.event.save()
# Finally perform a data clean up
self.__clear_data()
def __clear_data(self):
self.form_data = None
self.user = None
self.event_name = None
self.identifier = None
self.starts_at = None
self.ends_at = None
self.min_num_selections = 0
self.max_num_selections = 0
self.organisers[:] = []
self.trustees[:] = []
self.voters[:] = []
self.polls_options_map[:] = []
self.event = None