Added a whole lot of views.

Finished quiz API views
Finished question generator and answer eval
This commit is contained in:
2022-06-14 22:55:11 +01:00
parent a58f267586
commit 126bf9203c
15 changed files with 421 additions and 35 deletions

View File

@ -1,3 +1,4 @@
from .entry import Entry
from .test import Test
from .user import User
from .user import User
from .dataset import Dataset

View File

@ -0,0 +1,82 @@
from ..data import data
from ..modules import db
from ..tools.logs import write
from flask import flash, jsonify
from flask_login import current_user
from werkzeug.utils import secure_filename
from datetime import datetime
from json import dump, loads
from os import path, remove
from uuid import uuid4
class Dataset(db.Model):
id = db.Column(db.String(36), primary_key=True)
tests = db.relationship('Test', backref='dataset')
creator_id = db.Column(db.String(36), db.ForeignKey('user.id'))
date = db.Column(db.DateTime, nullable=False)
default = db.Column(db.Boolean, default=False, nullable=True)
def __repr__(self):
return f'<Dataset {self.id}> was added.'
@property
def generate_id(self): raise AttributeError('generate_id is not a readable attribute.')
generate_id.setter
def generate_id(self): self.id = uuid4.hex()
def make_default(self):
for dataset in Dataset.query.all():
dataset.default = False
self.default = True
db.session.commit()
write('system.log', f'Dataset {self.id} set as default by {current_user.get_username()}.')
flash(message='Dataset set as default.', category='success')
return True, f'Dataset set as default.'
def delete(self):
if self.default:
message = 'Cannot delete the default dataset.'
flash(message, 'error')
return False, jsonify({'error': message})
if Dataset.query.all().count() == 1:
message = 'Cannot delete the only dataset.'
flash(message, 'error')
return False, jsonify({'error': message})
write('system.log', f'Dataset {self.id} deleted by {current_user.get_username()}.')
filename = secure_filename('.'.join([self.id,'json']))
file_path = path.join(data, 'questions', filename)
remove(file_path)
db.session.delete(self)
db.session.commit()
return True, 'Dataset deleted.'
def create(self, upload, default:bool=False):
self.generate_id()
timestamp = datetime.now()
filename = secure_filename('.'.join([self.id,'json']))
file_path = path.join(data, 'questions', filename)
upload.stream.seek(0)
questions = loads(upload.read())
with open(file_path, 'w') as file:
dump(questions, file, indent=2)
self.date = timestamp
self.creator = current_user
if default: self.make_default()
write('system.log', f'New dataset {self.id} added by {current_user.get_username()}.')
db.session.add(self)
db.session.commit()
return True, 'Dataset uploaded.'
def check_file(self):
filename = secure_filename('.'.join([self.id,'json']))
file_path = path.join(data, 'questions', filename)
if not path.isfile(file_path): return False, 'Data file is missing.'
def get_file(self):
filename = secure_filename('.'.join([self.id,'json']))
file_path = path.join(data, 'questions', filename)
return file_path

View File

@ -8,6 +8,7 @@ from flask import jsonify
from flask_login import current_user
from datetime import datetime, timedelta
from uuid import uuid4
class Entry(db.Model):
@ -25,6 +26,15 @@ class Entry(db.Model):
answers = db.Column(JsonEncodedDict, nullable=True)
result = db.Column(JsonEncodedDict, nullable=True)
def __repr__(self):
return f'<New entry by {self.first_name} {self.surname}> was added with <id {self.id}>.'
@property
def generate_id(self): raise AttributeError('generate_id is not a readable attribute.')
generate_id.setter
def generate_id(self): self.id = uuid4.hex()
@property
def set_first_name(self): raise AttributeError('set_first_name is not a readable attribute.')
@ -63,10 +73,11 @@ class Entry(db.Model):
write('tests.log', f'New test started by {self.get_first_name()} {self.get_surname()}.')
db.session.commit()
def complete(self):
def complete(self, answers:dict=None, result:dict=None):
self.end_time = datetime.now()
self.answers = answers
write('tests.log', f'Test completed by {self.get_first_name()} {self.get_surname()}.')
delta = timedelta(minutes=self.test.time_limit)
delta = timedelta(minutes=self.test.time_limit+1)
if not self.test.time_limit or self.end_time <= self.start_time + delta:
self.status = 'finished'
self.valid = True

View File

@ -11,7 +11,7 @@ from datetime import datetime
from json import dump, loads
import os
import secrets
from uuid import uuid4
class Test(db.Model):
@ -21,18 +21,33 @@ class Test(db.Model):
end_date = db.Column(db.DateTime, nullable=True)
time_limit = db.Column(db.Integer, nullable=True)
creator_id = db.Column(db.String(36), db.ForeignKey('user.id'))
data = db.Column(db.String(36), nullable=False)
dataset_id = db.Column(db.String(36), db.ForeignKey('dataset.id'))
adjustments = db.Column(JsonEncodedDict, nullable=True)
entries = db.relationship('Entry', backref='test')
def __repr__(self):
return f'<test with code {self.code} was created by {current_user.get_username()}.>'
@property
def generate_id(self): raise AttributeError('generate_id is not a readable attribute.')
generate_id.setter
def generate_id(self): self.id = uuid4.hex()
@property
def generate_code(self): raise AttributeError('generate_code is not a readable attribute.')
generate_code.setter
def generate_code(self): self.code = secrets.token_hex(6).lower()
def get_code(self):
code = self.code.upper()
return ''.join([code[:4], code[4:8], code[8:]])
def create(self):
self.generate_id()
self.generate_code()
self.creator = current_user
db.session.add(self)
db.session.commit()
write('system.log', f'Test with code {self.code} created by {current_user.get_username()}.')

View File

@ -17,6 +17,7 @@ class User(UserMixin, db.Model):
reset_token = db.Column(db.String(20), nullable=True)
verification_token = db.Column(db.String(20), nullable=True)
tests = db.relationship('Test', backref='creator')
datasets = db.relationship('Dataset', backref='creator')
def __repr__(self):
return f'<user {self.username}> was added with <id {self.id}>.'
@ -52,6 +53,7 @@ class User(UserMixin, db.Model):
def get_email(self): return decrypt(self.email)
def register(self, notify:bool=False):
self.generate_id()
users = User.query.all()
for user in users:
if user.get_username() == self.get_username(): return False, f'Username {self.get_username()} already in use.'
@ -88,17 +90,19 @@ class User(UserMixin, db.Model):
self.reset_token = self.verification_token = None
db.session.commit()
def delete(self):
def delete(self, notify:bool=False):
username = self.get_username()
db.session.delete(self)
db.session.commit()
write('users.log', f'User \'{username}\' was deleted by \'{current_user.get_username()}\'.')
message = f'User \'{username}\' was deleted by \'{current_user.get_username()}\'.'
write('users.log', message)
return True, message
def update(self, password:str=None, email:str=None):
def update(self, password:str=None, email:str=None, notify:bool=False):
if not password and not email: return False, jsonify({'error': 'There were no changes requested.'})
if password: self.set_password(password)
if email: self.set_email(email)
db.session.commit()
message = f'Information for user {self.get_username()} has been updated by {current_user.get_username()}.'
write('system.log', message)
return True, jsonify({'success': message})
return True, message