Changed the layer at which json files are parsed

Updated dataset database model
Updated create and edit function to use data list instead of file
This commit is contained in:
Vivek Santayana 2022-06-22 01:55:55 +01:00
parent 6bbdb8fced
commit c6c62fc34c
2 changed files with 50 additions and 19 deletions

View File

@ -5,12 +5,13 @@ from ..tools.forms import get_dataset_choices, get_time_options, send_errors_to_
from ..tools.data import check_is_json, validate_json from ..tools.data import check_is_json, validate_json
from ..tools.test import answer_options, get_correct_answers from ..tools.test import answer_options, get_correct_answers
from flask import Blueprint, jsonify, render_template, redirect, request, session from flask import abort, Blueprint, jsonify, render_template, redirect, request, send_file, session
from flask.helpers import flash, url_for from flask.helpers import flash, url_for
from flask_login import current_user, login_required from flask_login import current_user, login_required
from datetime import date, datetime from datetime import date, datetime
from json import loads from json import loads
from os import path
import secrets import secrets
admin = Blueprint( admin = Blueprint(
@ -207,10 +208,13 @@ def _questions():
if form.validate_on_submit(): if form.validate_on_submit():
upload = form.data_file.data upload = form.data_file.data
if not check_is_json(upload): return jsonify({'error': 'Invalid file. Please upload a JSON file.'}), 400 if not check_is_json(upload): return jsonify({'error': 'Invalid file. Please upload a JSON file.'}), 400
if not validate_json(upload): return jsonify({'error': 'The data in the file is invalid.'}), 400 upload.stream.seek(0)
data = loads(upload.read())
if not validate_json(data=data): return jsonify({'error': 'The data in the file is invalid.'}), 400
new_dataset = Dataset() new_dataset = Dataset()
new_dataset.set_name(request.form.get('name'))
success, message = new_dataset.create( success, message = new_dataset.create(
upload = upload, data = data,
default = request.form.get('default') default = request.form.get('default')
) )
if success: return jsonify({'success': message}), 200 if success: return jsonify({'success': message}), 200
@ -220,18 +224,25 @@ def _questions():
data = Dataset.query.all() data = Dataset.query.all()
return render_template('/admin/settings/questions.html', form=form, data=data) return render_template('/admin/settings/questions.html', form=form, data=data)
@admin.route('/settings/questions/edit/', methods=['POST']) @admin.route('/settings/questions/delete/', methods=['POST'])
@login_required @login_required
def _edit_questions(): def _edit_questions():
id = request.get_json()['id'] id = request.get_json()['id']
action = request.get_json()['action'] action = request.get_json()['action']
if action not in ['defailt', 'delete']: return jsonify({'error': 'Invalid action.'}), 400 if not action == 'delete': return jsonify({'error': 'Invalid action.'}), 400
dataset = Dataset.query.filter_by(id=id).first() dataset = Dataset.query.filter_by(id=id).first()
if action == 'delete': success, message = dataset.delete() if action == 'delete': success, message = dataset.delete()
elif action == 'default': success, message = dataset.make_default()
if success: return jsonify({'success': message}), 200 if success: return jsonify({'success': message}), 200
return jsonify({'error': message}), 400 return jsonify({'error': message}), 400
@admin.route('/settings/questions/download/<string:id>/')
@login_required
def _download(id:str):
dataset = Dataset.query.filter_by(id=id).first()
if not dataset: return abort(404)
data_path = path.abspath(dataset.get_file())
return send_file(data_path, as_attachment=True, attachment_filename=f'{dataset.get_name()}.json')
@admin.route('/tests/<string:filter>/', methods=['GET']) @admin.route('/tests/<string:filter>/', methods=['GET'])
@admin.route('/tests/', methods=['GET']) @admin.route('/tests/', methods=['GET'])
@login_required @login_required

View File

@ -1,4 +1,5 @@
from ..extensions import db from ..extensions import db
from ..tools.encryption import decrypt, encrypt
from ..tools.logs import write from ..tools.logs import write
from flask import flash from flask import flash
@ -7,7 +8,7 @@ from flask_login import current_user
from werkzeug.utils import secure_filename from werkzeug.utils import secure_filename
from datetime import datetime from datetime import datetime
from json import dump, loads from json import dump
from os import path, remove from os import path, remove
from pathlib import Path from pathlib import Path
from uuid import uuid4 from uuid import uuid4
@ -15,13 +16,16 @@ from uuid import uuid4
class Dataset(db.Model): class Dataset(db.Model):
id = db.Column(db.String(36), primary_key=True) id = db.Column(db.String(36), primary_key=True)
name = db.Column(db.String(128), nullable=False)
tests = db.relationship('Test', backref='dataset') tests = db.relationship('Test', backref='dataset')
creator_id = db.Column(db.String(36), db.ForeignKey('user.id')) creator_id = db.Column(db.String(36), db.ForeignKey('user.id'))
date = db.Column(db.DateTime, nullable=False) date = db.Column(db.DateTime, nullable=False)
default = db.Column(db.Boolean, default=False, nullable=True) default = db.Column(db.Boolean, default=False, nullable=True)
accessed = db.Column(db.DateTime, nullable=True)
locked = db.Column(db.Boolean, default=False, nullable=True)
def __repr__(self): def __repr__(self):
return f'<Dataset {self.id}> was added.' return f'<Dataset {self.id}>.'
@property @property
def generate_id(self): raise AttributeError('generate_id is not a readable attribute.') def generate_id(self): raise AttributeError('generate_id is not a readable attribute.')
@ -29,6 +33,14 @@ class Dataset(db.Model):
generate_id.setter generate_id.setter
def generate_id(self): self.id = uuid4().hex def generate_id(self): self.id = uuid4().hex
@property
def set_name(self): raise AttributeError('set_name is not a readable attribute.')
set_name.setter
def set_name(self, name:str): self.name = encrypt(name)
def get_name(self): return decrypt(self.name)
def make_default(self): def make_default(self):
for dataset in Dataset.query.all(): for dataset in Dataset.query.all():
dataset.default = False dataset.default = False
@ -43,7 +55,7 @@ class Dataset(db.Model):
message = 'Cannot delete the default dataset.' message = 'Cannot delete the default dataset.'
flash(message, 'error') flash(message, 'error')
return False, message return False, message
if Dataset.query.all().count() == 1: if Dataset.query.count() == 1:
message = 'Cannot delete the only dataset.' message = 'Cannot delete the only dataset.'
flash(message, 'error') flash(message, 'error')
return False, message return False, message
@ -56,23 +68,19 @@ class Dataset(db.Model):
db.session.commit() db.session.commit()
return True, 'Dataset deleted.' return True, 'Dataset deleted.'
def create(self, upload, default:bool=False): def create(self, data:list, default:bool=False):
self.generate_id() self.generate_id()
timestamp = datetime.now() timestamp = datetime.now()
filename = secure_filename('.'.join([self.id,'json'])) file_path = self.get_file()
data = Path(app.config.get('DATA'))
file_path = path.join(data, 'questions', filename)
upload.stream.seek(0)
questions = loads(upload.read())
with open(file_path, 'w') as file: with open(file_path, 'w') as file:
dump(questions, file, indent=2) dump(data, file, indent=2)
self.date = timestamp self.date = timestamp
self.creator = current_user self.creator = current_user
if default: self.make_default() if default: self.make_default()
write('system.log', f'New dataset {self.id} added by {current_user.get_username()}.') write('system.log', f'New dataset {self.get_name()} added by {current_user.get_username()}.')
db.session.add(self) db.session.add(self)
db.session.commit() db.session.commit()
return True, 'Dataset uploaded.' return True, 'Dataset created.'
def check_file(self): def check_file(self):
filename = secure_filename('.'.join([self.id,'json'])) filename = secure_filename('.'.join([self.id,'json']))
@ -86,3 +94,15 @@ class Dataset(db.Model):
data = Path(app.config.get('DATA')) data = Path(app.config.get('DATA'))
file_path = path.join(data, 'questions', filename) file_path = path.join(data, 'questions', filename)
return file_path return file_path
def update(self, data:list=None, default:bool=False):
self.date = datetime.now()
if default: self.make_default()
file_path = self.get_file()
with open(file_path, 'w') as file:
dump(data, file, indent=2)
write('system.log', f'Dataset {self.id} edited by {current_user.get_username()}.')
flash(f'Dataset {self.name} successfully edited.', 'success')
db.session.add(self)
db.session.commit()
return True, 'Dataset successfully edited.'