Move corpora views, and forms in package.

This commit is contained in:
Patrick Jentsch 2019-10-31 10:25:48 +01:00
parent 8fb52fcd31
commit 3135eb0897
8 changed files with 179 additions and 194 deletions

View File

@ -29,6 +29,9 @@ def create_app(config_name):
from .auth import auth as auth_blueprint from .auth import auth as auth_blueprint
app.register_blueprint(auth_blueprint, url_prefix='/auth') app.register_blueprint(auth_blueprint, url_prefix='/auth')
from .corpora import corpora as corpora_blueprint
app.register_blueprint(corpora_blueprint, url_prefix='/corpora')
from .main import main as main_blueprint from .main import main as main_blueprint
app.register_blueprint(main_blueprint) app.register_blueprint(main_blueprint)

6
app/corpora/__init__.py Normal file
View File

@ -0,0 +1,6 @@
from flask import Blueprint
corpora = Blueprint('corpora', __name__)
from . import views

View File

@ -18,7 +18,7 @@ class AddCorpusFileForm(FlaskForm):
'.vrt') '.vrt')
class CreateCorpusForm(FlaskForm): class AddCorpusForm(FlaskForm):
description = StringField('Description', description = StringField('Description',
validators=[DataRequired(), Length(1, 64)]) validators=[DataRequired(), Length(1, 64)])
submit = SubmitField() submit = SubmitField()

150
app/corpora/views.py Normal file
View File

@ -0,0 +1,150 @@
from flask import (abort, current_app, flash, redirect, request,
render_template, url_for, send_from_directory)
from flask_login import current_user, login_required
from . import corpora
from .forms import (AddCorpusFileForm, AddCorpusForm, QueryDownloadForm,
QueryForm)
from .. import db
from ..models import Corpus, CorpusFile
from werkzeug.utils import secure_filename
import os
import threading
import logging
@corpora.route('/add', methods=['POST'])
@login_required
def add_corpus():
add_corpus_form = AddCorpusForm()
if not add_corpus_form.validate_on_submit():
abort(400)
corpus = Corpus(creator=current_user,
description=add_corpus_form.description.data,
title=add_corpus_form.title.data)
db.session.add(corpus)
db.session.commit()
dir = os.path.join(current_app.config['OPAQUE_STORAGE_DIRECTORY'],
str(corpus.user_id), 'corpora', str(corpus.id))
try:
os.makedirs(dir)
except OSError:
flash('OSError!')
db.session.remove(corpus)
db.session.commit()
flash('Corpus created!')
return redirect(url_for('corpora.corpus', corpus_id=corpus.id))
@corpora.route('/<int:corpus_id>')
@login_required
def corpus(corpus_id):
corpus = Corpus.query.get_or_404(corpus_id)
if not (corpus.creator == current_user or current_user.is_administrator()):
abort(403)
return render_template('corpora/corpus.html.j2',
add_corpus_file_form=AddCorpusFileForm(),
corpus=corpus, title='Corpus')
@corpora.route('/<int:corpus_id>/analysis', methods=['GET', 'POST'])
@login_required
def corpus_analysis(corpus_id):
logger = logging.getLogger(__name__)
corpus = Corpus.query.get_or_404(corpus_id)
query = request.args.get('query')
logger.warning('Query first: {}'.format(query))
hits_per_page = request.args.get('hits_per_page', 30)
context = request.args.get('context', 10)
dl_form = QueryDownloadForm()
form = QueryForm(hits_per_page=hits_per_page, context=context, query=query)
if form.validate_on_submit():
logger = logging.getLogger(__name__)
logger.warning('Data has been sent!')
logger.warning('Data labels: {data}'.format(data=[data for data in form.data]))
logger.warning('Query Second: {q}'.format(q=form.query.data))
logger.warning('Hits: {hits}'.format(hits=form.hits_per_page.data))
logger.warning('Context: {context}'.format(context=form.context.data))
flash('Query has been sent!')
query = form.query.data
hits_per_page = form.hits_per_page.data
context = form.context.data
logger.warning('Query Thrid: {sq}'.format(sq=query))
return redirect(url_for('corpora.corpus_analysis', corpus_id=corpus_id,
query=query, hits_per_page=hits_per_page,
context=context))
return render_template('corpora/corpus_analysis.html.j2', corpus=corpus,
form=form, dl_form=dl_form,
title='Corpus: {}'.format(corpus.title))
@corpora.route('/<int:corpus_id>/delete')
@login_required
def delete_corpus(corpus_id):
corpus = Corpus.query.get_or_404(corpus_id)
if not (corpus.creator == current_user or current_user.is_administrator()):
abort(403)
delete_thread = threading.Thread(corpus.delete())
delete_thread.start()
flash('Corpus deleted!')
return redirect(url_for('main.dashboard'))
@corpora.route('/<int:corpus_id>/files/add', methods=['POST'])
@login_required
def add_corpus_file(corpus_id):
corpus = Corpus.query.get_or_404(corpus_id)
if not (corpus.creator == current_user or current_user.is_administrator()):
abort(403)
add_corpus_file_form = AddCorpusFileForm()
if not add_corpus_file_form.validate_on_submit():
abort(400)
file = add_corpus_file_form.file.data
filename = secure_filename(file.filename)
for corpus_file in corpus.files:
if filename == corpus_file.filename:
flash('File already registered to this corpus.')
return redirect(url_for('corpora.corpus', corpus_id=corpus_id))
# Save the file
dir = os.path.join(str(corpus.user_id), 'corpora', str(corpus.id))
file.save(os.path.join(current_app.config['OPAQUE_STORAGE_DIRECTORY'], dir,
filename))
author = add_corpus_file_form.author.data
publishing_year = add_corpus_file_form.publishing_year.data
title = add_corpus_file_form.title.data
corpus_file = CorpusFile(author=author, corpus=corpus, dir=dir,
filename=filename,
publishing_year=publishing_year, title=title)
db.session.add(corpus_file)
db.session.commit()
flash('Corpus file added!')
return redirect(url_for('corpora.corpus', corpus_id=corpus_id))
@corpora.route('/<int:corpus_id>/files/<int:corpus_file_id>/delete')
@login_required
def delete_corpus_file(corpus_id, corpus_file_id):
corpus_file = CorpusFile.query.get_or_404(corpus_file_id)
if not corpus_file.corpus_id == corpus_id:
abort(404)
if not (corpus_file.corpus.creator == current_user
or current_user.is_administrator()):
abort(403)
delete_thread = threading.Thread(corpus_file.delete())
delete_thread.start()
flash('Corpus file deleted!')
return redirect(url_for('corpora.corpus', corpus_id=corpus_id))
@corpora.route('/<int:corpus_id>/files/<int:corpus_file_id>/download')
@login_required
def download_corpus_file(corpus_id, corpus_file_id):
corpus_file = CorpusFile.query.get_or_404(corpus_file_id)
if not corpus_file.corpus_id == corpus_id:
abort(404)
if not (corpus_file.corpus.creator == current_user
or current_user.is_administrator()):
abort(403)
dir = os.path.join(current_app.config['OPAQUE_STORAGE_DIRECTORY'],
corpus_file.dir)
return send_from_directory(as_attachment=True, directory=dir,
filename=corpus_file.filename)

View File

@ -1,15 +1,12 @@
from app.utils import background_delete_job from app.utils import background_delete_job
from flask import (abort, current_app, flash, redirect, request, from flask import (abort, current_app, flash, redirect, render_template,
render_template, url_for, send_from_directory) send_from_directory, url_for)
from flask_login import current_user, login_required from flask_login import current_user, login_required
from . import main from . import main
from .forms import AddCorpusFileForm, CreateCorpusForm, QueryForm, QueryDownloadForm from ..corpora.forms import AddCorpusForm
from .. import db from ..models import Job, JobInput, JobResult
from ..models import Corpus, CorpusFile, Job, JobInput, JobResult
from werkzeug.utils import secure_filename
import os import os
import threading import threading
import logging
@main.route('/') @main.route('/')
@ -17,182 +14,11 @@ def index():
return render_template('main/index.html.j2', title='Opaque') return render_template('main/index.html.j2', title='Opaque')
@main.route('/corpora/new', methods=['POST']) @main.route('/dashboard')
@login_required
def corpus_new():
create_corpus_form = CreateCorpusForm()
if create_corpus_form.validate_on_submit():
corpus = Corpus(creator=current_user,
description=create_corpus_form.description.data,
title=create_corpus_form.title.data)
db.session.add(corpus)
db.session.commit()
dir = os.path.join(current_app.config['OPAQUE_STORAGE_DIRECTORY'],
str(corpus.user_id),
'corpora',
str(corpus.id))
try:
os.makedirs(dir)
except OSError:
flash('OSError!')
db.session.remove(corpus)
db.session.commit()
flash('Corpus created!')
return redirect(url_for('main.corpus', corpus_id=corpus.id))
@main.route('/corpora/<int:corpus_id>')
@login_required
def corpus(corpus_id):
corpus = Corpus.query.get_or_404(corpus_id)
if not (corpus.creator == current_user or current_user.is_administrator()):
abort(403)
return render_template('main/corpora/corpus.html.j2',
add_corpus_file_form=AddCorpusFileForm(),
corpus=corpus,
title='Corpus')
@main.route('/corpora/<int:corpus_id>/analysis', methods=['GET', 'POST'])
@login_required
def corpus_analysis(corpus_id):
logger = logging.getLogger(__name__)
corpus = Corpus.query.get_or_404(corpus_id)
query = request.args.get('query')
logger.warning('Query first: {}'.format(query))
hits_per_page = request.args.get('hits_per_page', 30)
context = request.args.get('context', 10)
dl_form = QueryDownloadForm()
form = QueryForm(hits_per_page=hits_per_page, context=context, query=query)
if form.validate_on_submit():
logger = logging.getLogger(__name__)
logger.warning('Data has been sent!')
logger.warning('Data labels: {data}'.format(data=[data for data in form.data]))
logger.warning('Query Second: {q}'.format(q=form.query.data))
logger.warning('Hits: {hits}'.format(hits=form.hits_per_page.data))
logger.warning('Context: {context}'.format(context=form.context.data))
flash('Query has been sent!')
query = form.query.data
hits_per_page = form.hits_per_page.data
context = form.context.data
logger.warning('Query Thrid: {sq}'.format(sq=query))
return redirect(url_for('main.corpus_analysis',
corpus_id=corpus_id,
query=query,
hits_per_page=hits_per_page,
context=context))
return render_template('main/corpora/corpus_analysis.html.j2',
corpus=corpus,
form=form,
dl_form=dl_form,
title='Corpus: ' + corpus.title)
@main.route('/corpora/<int:corpus_id>/delete')
@login_required
def corpus_delete(corpus_id):
corpus = Corpus.query.get_or_404(corpus_id)
if not (corpus.creator == current_user or current_user.is_administrator()):
abort(403)
delete_thread = threading.Thread(corpus.delete())
delete_thread.start()
flash('Corpus has been deleted!')
return redirect(url_for('main.dashboard'))
@main.route('/corpora/<int:corpus_id>/files/new', methods=['POST'])
@login_required
def corpus_file_new(corpus_id):
corpus = Corpus.query.get_or_404(corpus_id)
if not (corpus.creator == current_user or current_user.is_administrator()):
abort(403)
add_corpus_file_form = AddCorpusFileForm()
if not add_corpus_file_form.validate_on_submit():
abort(400)
file = add_corpus_file_form.file.data
filename = secure_filename(file.filename)
for corpus_file in corpus.files:
if filename == corpus_file.filename:
flash('File already registered to this corpus.')
return redirect(url_for('main.corpus', corpus_id=corpus_id))
# Save the file
dir = os.path.join(str(corpus.user_id), 'corpora', str(corpus.id))
file_path = os.path.join(
current_app.config['OPAQUE_STORAGE_DIRECTORY'], dir, filename
)
file.save(file_path)
# Gather information to create new corpus file database entry
author = add_corpus_file_form.author.data
publishing_year = add_corpus_file_form.publishing_year.data
title = add_corpus_file_form.title.data
corpus_file = CorpusFile(author=author,
corpus=corpus,
dir=dir,
filename=filename,
publishing_year=publishing_year,
title=title)
db.session.add(corpus_file)
db.session.commit()
flash('Corpus file added!')
return redirect(url_for('main.corpus', corpus_id=corpus_id))
@main.route('/corpora/<int:corpus_id>/files/<int:corpus_file_id>/delete')
@login_required
def corpus_file_delete(corpus_id, corpus_file_id):
corpus_file = CorpusFile.query.get_or_404(corpus_file_id)
if not corpus_file.corpus_id == corpus_id:
abort(404)
if not (corpus_file.corpus.creator == current_user
or current_user.is_administrator()):
abort(403)
delete_thread = threading.Thread(corpus_file.delete())
delete_thread.start()
flash('Corpus file deleted!')
return redirect(url_for('main.corpus', corpus_id=corpus_id))
@main.route('/corpora/<int:corpus_id>/files/<int:corpus_file_id>/download')
@login_required
def corpus_file_download(corpus_id, corpus_file_id):
corpus_file = CorpusFile.query.get_or_404(corpus_file_id)
if not corpus_file.corpus_id == corpus_id:
abort(404)
if not (corpus_file.corpus.creator == current_user
or current_user.is_administrator()):
abort(403)
dir = os.path.join(current_app.config['OPAQUE_STORAGE_DIRECTORY'],
corpus_file.dir)
return send_from_directory(as_attachment=True,
directory=dir,
filename=corpus_file.filename)
@main.route('/dashboard', methods=['GET', 'POST'])
@login_required @login_required
def dashboard(): def dashboard():
create_corpus_form = CreateCorpusForm()
if create_corpus_form.validate_on_submit():
corpus = Corpus(creator=current_user._get_current_object(),
description=create_corpus_form.description.data,
title=create_corpus_form.title.data)
db.session.add(corpus)
db.session.commit()
dir = os.path.join(current_app.config['OPAQUE_STORAGE_DIRECTORY'],
str(corpus.user_id),
'corpora',
str(corpus.id))
try:
os.makedirs(dir)
except OSError:
flash('OSError!')
db.session.remove(corpus)
db.session.commit()
flash('Corpus created!')
return redirect(url_for('main.dashboard'))
return render_template('main/dashboard.html.j2', return render_template('main/dashboard.html.j2',
create_corpus_form=create_corpus_form, add_corpus_form=AddCorpusForm(), title='Dashboard')
title='Dashboard')
@main.route('/jobs/<int:job_id>') @main.route('/jobs/<int:job_id>')

View File

@ -32,7 +32,7 @@
</div> </div>
</div> </div>
<span class="card-title">Actions</span> <span class="card-title">Actions</span>
<a href="{{ url_for('main.corpus_analysis', corpus_id=corpus.id) }}" class="waves-effect waves-light btn"> <a href="{{ url_for('corpora.corpus_analysis', corpus_id=corpus.id) }}" class="waves-effect waves-light btn">
<i class="material-icons left">help</i>Analyse <i class="material-icons left">help</i>Analyse
</a> </a>
<a data-target="add-corpus-file-modal" class="waves-effect waves-light btn modal-trigger"> <a data-target="add-corpus-file-modal" class="waves-effect waves-light btn modal-trigger">
@ -70,8 +70,8 @@
<td>{{ file.publishing_year }}</td> <td>{{ file.publishing_year }}</td>
<td class="right-align"> <td class="right-align">
<a class="waves-effect waves-light btn-small"><i class="material-icons">edit</i></a> <a class="waves-effect waves-light btn-small"><i class="material-icons">edit</i></a>
<a class="waves-effect waves-light btn-small" href="{{ url_for('main.corpus_file_download', corpus_file_id=file.id, corpus_id=corpus.id) }}"><i class="material-icons">file_download</i></a> <a class="waves-effect waves-light btn-small" href="{{ url_for('corpora.download_corpus_file', corpus_file_id=file.id, corpus_id=corpus.id) }}"><i class="material-icons">file_download</i></a>
<a class="waves-effect waves-light btn-small red" href="{{ url_for('main.corpus_file_delete', corpus_file_id=file.id, corpus_id=corpus.id) }}"><i class="material-icons">delete</i></a> <a class="waves-effect waves-light btn-small red" href="{{ url_for('corpora.delete_corpus_file', corpus_file_id=file.id, corpus_id=corpus.id) }}"><i class="material-icons">delete</i></a>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
@ -86,7 +86,7 @@
<div id="add-corpus-file-modal" class="modal"> <div id="add-corpus-file-modal" class="modal">
<div class="modal-content"> <div class="modal-content">
<h4>Add corpus file</h4> <h4>Add corpus file</h4>
<form action="{{ url_for('main.corpus_file_new', corpus_id=corpus.id) }}" method="POST" enctype="multipart/form-data"> <form action="{{ url_for('corpora.add_corpus_file', corpus_id=corpus.id) }}" method="POST" enctype="multipart/form-data">
{{ add_corpus_file_form.hidden_tag() }} {{ add_corpus_file_form.hidden_tag() }}
<div class="row"> <div class="row">
<div class="col s12 m4"> <div class="col s12 m4">
@ -148,7 +148,7 @@
All files will be permanently deleted.</p> All files will be permanently deleted.</p>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<a href="{{ url_for('main.corpus_delete', corpus_id=corpus.id) }}" class="modal-close waves-effect waves-green btn red"><i class="material-icons left">delete</i>Delete Corpus</a> <a href="{{ url_for('corpora.delete_corpus', corpus_id=corpus.id) }}" class="modal-close waves-effect waves-green btn red"><i class="material-icons left">delete</i>Delete Corpus</a>
<a href="#!" class="modal-close waves-effect waves-green btn cancel">Cancel</a> <a href="#!" class="modal-close waves-effect waves-green btn cancel">Cancel</a>
</div> </div>
</div> </div>

View File

@ -88,15 +88,15 @@
<div id="new-corpus-modal" class="modal"> <div id="new-corpus-modal" class="modal">
<div class="modal-content"> <div class="modal-content">
<h4>New corpus</h4> <h4>New corpus</h4>
<form action="{{ url_for('main.corpus_new') }}" method="POST"> <form action="{{ url_for('corpora.add_corpus') }}" method="POST">
{{ create_corpus_form.hidden_tag() }} {{ add_corpus_form.hidden_tag() }}
<div class="row"> <div class="row">
<div class="col s12 m4"> <div class="col s12 m4">
<div class="input-field"> <div class="input-field">
<i class="material-icons prefix">title</i> <i class="material-icons prefix">title</i>
{{ create_corpus_form.title(data_length='32') }} {{ add_corpus_form.title(data_length='32') }}
{{ create_corpus_form.title.label }} {{ add_corpus_form.title.label }}
{% for error in create_corpus_form.title.errors %} {% for error in add_corpus_form.title.errors %}
<span class="helper-text red-text">{{ error }}</span> <span class="helper-text red-text">{{ error }}</span>
{% endfor %} {% endfor %}
</div> </div>
@ -104,9 +104,9 @@
<div class="col s12 m8"> <div class="col s12 m8">
<div class="input-field"> <div class="input-field">
<i class="material-icons prefix">description</i> <i class="material-icons prefix">description</i>
{{ create_corpus_form.description(data_length='255') }} {{ add_corpus_form.description(data_length='255') }}
{{ create_corpus_form.description.label }} {{ add_corpus_form.description.label }}
{% for error in create_corpus_form.description.errors %} {% for error in add_corpus_form.description.errors %}
<span class="helper-text red-text">{{ error }}</span> <span class="helper-text red-text">{{ error }}</span>
{% endfor %} {% endfor %}
</div> </div>