mirror of
https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
synced 2025-06-14 10:00:40 +00:00
Add a parallel package for query results.
This commit is contained in:
5
web/app/query_results/__init__.py
Normal file
5
web/app/query_results/__init__.py
Normal file
@ -0,0 +1,5 @@
|
||||
from flask import Blueprint
|
||||
|
||||
|
||||
query_results = Blueprint('query_results', __name__)
|
||||
from . import views # noqa
|
21
web/app/query_results/forms.py
Normal file
21
web/app/query_results/forms.py
Normal file
@ -0,0 +1,21 @@
|
||||
from flask_wtf import FlaskForm
|
||||
from werkzeug.utils import secure_filename
|
||||
from wtforms import FileField, StringField, SubmitField, ValidationError
|
||||
from wtforms.validators import DataRequired, Length
|
||||
|
||||
|
||||
class AddQueryResultForm(FlaskForm):
|
||||
'''
|
||||
Form used to import one result json file.
|
||||
'''
|
||||
description = StringField('Description',
|
||||
validators=[DataRequired(), Length(1, 255)])
|
||||
file = FileField('File', validators=[DataRequired()])
|
||||
title = StringField('Title', validators=[DataRequired(), Length(1, 32)])
|
||||
submit = SubmitField()
|
||||
|
||||
def validate_file(self, field):
|
||||
if not field.data.filename.lower().endswith('.json'):
|
||||
raise ValidationError('File does not have an approved extension: '
|
||||
'.json')
|
||||
field.data.filename = secure_filename(field.data.filename)
|
13
web/app/query_results/tasks.py
Normal file
13
web/app/query_results/tasks.py
Normal file
@ -0,0 +1,13 @@
|
||||
from .. import db
|
||||
from ..decorators import background
|
||||
from ..models import QueryResult
|
||||
|
||||
|
||||
@background
|
||||
def delete_query_result(query_result_id, *args, **kwargs):
|
||||
with kwargs['app'].app_context():
|
||||
query_result = QueryResult.query.get(query_result_id)
|
||||
if query_result is None:
|
||||
raise Exception('QueryResult {} not found'.format(query_result_id))
|
||||
query_result.delete()
|
||||
db.session.commit()
|
144
web/app/query_results/views.py
Normal file
144
web/app/query_results/views.py
Normal file
@ -0,0 +1,144 @@
|
||||
from . import query_results
|
||||
from . import tasks
|
||||
from .. import db
|
||||
from ..corpora.forms import DisplayOptionsForm
|
||||
from ..models import QueryResult
|
||||
from .forms import AddQueryResultForm
|
||||
from flask import (abort, current_app, flash, make_response, redirect,
|
||||
render_template, request, send_from_directory, url_for)
|
||||
from flask_login import current_user, login_required
|
||||
import json
|
||||
import os
|
||||
from jsonschema import validate
|
||||
|
||||
|
||||
@query_results.route('/add', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def add_query_result():
|
||||
'''
|
||||
View to import a result as a json file.
|
||||
'''
|
||||
add_query_result_form = AddQueryResultForm(prefix='add-query-result-form')
|
||||
if add_query_result_form.is_submitted():
|
||||
if not add_query_result_form.validate():
|
||||
return make_response(add_query_result_form.errors, 400)
|
||||
query_result = QueryResult(
|
||||
creator=current_user,
|
||||
description=add_query_result_form.description.data,
|
||||
filename=add_query_result_form.file.data.filename,
|
||||
title=add_query_result_form.title.data
|
||||
)
|
||||
db.session.add(query_result)
|
||||
db.session.commit()
|
||||
# create paths to save the uploaded json file
|
||||
query_result_dir = os.path.join(current_app.config['NOPAQUE_STORAGE'],
|
||||
str(current_user.id),
|
||||
'query_results',
|
||||
str(query_result.id))
|
||||
try:
|
||||
os.makedirs(query_result_dir)
|
||||
except Exception:
|
||||
db.session.delete(query_result)
|
||||
db.session.commit()
|
||||
flash('Internal Server Error', 'error')
|
||||
redirect_url = url_for('query_results.add_query_result')
|
||||
return make_response({'redirect_url': redirect_url}, 500)
|
||||
# save the uploaded file
|
||||
query_result_file_path = os.path.join(query_result_dir,
|
||||
query_result.filename)
|
||||
add_query_result_form.file.data.save(query_result_file_path)
|
||||
# parse json from file
|
||||
with open(query_result_file_path, 'r') as file:
|
||||
query_result_file_content = json.load(file)
|
||||
# parse json schema
|
||||
with open('app/static/json_schema/nopaque_cqi_py_results_schema.json', 'r') as file: # noqa
|
||||
schema = json.load(file)
|
||||
try:
|
||||
# validate imported json file
|
||||
validate(instance=query_result_file_content, schema=schema)
|
||||
except Exception:
|
||||
tasks.delete_query_result(query_result.id)
|
||||
flash('Uploaded file is invalid', 'result')
|
||||
redirect_url = url_for('query_results.add_query_result')
|
||||
return make_response({'redirect_url': redirect_url}, 201)
|
||||
query_result_file_content.pop('matches')
|
||||
query_result_file_content.pop('cpos_lookup')
|
||||
query_result.query_metadata = query_result_file_content
|
||||
db.session.commit()
|
||||
flash('Query result added!', 'result')
|
||||
redirect_url = url_for('query_results.query_result',
|
||||
query_result_id=query_result.id)
|
||||
return make_response({'redirect_url': redirect_url}, 201)
|
||||
return render_template('query_results/add_query_result.html.j2',
|
||||
add_query_result_form=add_query_result_form,
|
||||
title='Add query result')
|
||||
|
||||
|
||||
@query_results.route('/<int:query_result_id>')
|
||||
@login_required
|
||||
def query_result(query_result_id):
|
||||
query_result = QueryResult.query.get_or_404(query_result_id)
|
||||
if not (query_result.creator == current_user
|
||||
or current_user.is_administrator()):
|
||||
abort(403)
|
||||
return render_template('query_results/query_result.html.j2',
|
||||
query_result=query_result,
|
||||
title='Query result')
|
||||
|
||||
|
||||
@query_results.route('/<int:query_result_id>/inspect')
|
||||
@login_required
|
||||
def inspect_query_result(query_result_id):
|
||||
'''
|
||||
View to inspect one importe result file in a corpus analysis like interface
|
||||
'''
|
||||
query_result = QueryResult.query.get_or_404(query_result_id)
|
||||
if not (query_result.creator == current_user
|
||||
or current_user.is_administrator()):
|
||||
abort(403)
|
||||
display_options_form = DisplayOptionsForm(
|
||||
prefix='display-options-form',
|
||||
results_per_page=request.args.get('results_per_page', 30),
|
||||
result_context=request.args.get('context', 20)
|
||||
)
|
||||
query_result_file_path = os.path.join(
|
||||
current_app.config['NOPAQUE_STORAGE'],
|
||||
str(current_user.id),
|
||||
'query_results',
|
||||
str(query_result.id),
|
||||
query_result.filename
|
||||
)
|
||||
with open(query_result_file_path, 'r') as query_result_file:
|
||||
query_result_content = json.load(query_result_file)
|
||||
return render_template('query_results/inspect_query_result.html.j2',
|
||||
display_options_form=display_options_form,
|
||||
query_result_content=query_result_content,
|
||||
title='Inspect query result')
|
||||
|
||||
|
||||
@query_results.route('/<int:query_result_id>/delete')
|
||||
@login_required
|
||||
def delete_query_result(query_result_id):
|
||||
query_result = QueryResult.query.get_or_404(query_result_id)
|
||||
if not (query_result.creator == current_user
|
||||
or current_user.is_administrator()):
|
||||
abort(403)
|
||||
tasks.delete_result(query_result_id)
|
||||
flash('Query result deleted!', 'result')
|
||||
return redirect(url_for('main.dashboard'))
|
||||
|
||||
|
||||
@query_results.route('/<int:query_result_id>/download')
|
||||
@login_required
|
||||
def download_query_result(query_result_id):
|
||||
query_result = QueryResult.query.get_or_404(query_result_id)
|
||||
if not (query_result.creator == current_user
|
||||
or current_user.is_administrator()):
|
||||
abort(403)
|
||||
query_result_dir = os.path.join(current_app.config['NOPAQUE_STORAGE'],
|
||||
str(current_user.id),
|
||||
'query_results',
|
||||
str(query_result.id))
|
||||
return send_from_directory(as_attachment=True,
|
||||
directory=query_result_dir,
|
||||
filename=query_result.filename)
|
Reference in New Issue
Block a user