Skip to content
Snippets Groups Projects

WIP: Reforma importů

Closed
Martin Marešrequested to merge
mj/import into master
1 open thread

Files

@@ -2,7 +2,6 @@ from dataclasses import dataclass
from flask import render_template, g, redirect, url_for, flash, request
from flask_wtf import FlaskForm
import flask_wtf.file
import locale
import os
import secrets
from sqlalchemy import func, and_
@@ -13,9 +12,9 @@ import werkzeug.exceptions
import wtforms
import mo
import mo.csv
from mo.csv import FileFormat
import mo.db as db
import mo.imports
from mo.imports import ImportType, create_import
import mo.jobs.submit
import mo.rights
from mo.rights import Right, Rights
@@ -28,8 +27,19 @@ import wtforms.validators as validators
class ImportForm(FlaskForm):
file = flask_wtf.file.FileField("Soubor", validators=[flask_wtf.file.FileRequired()])
file = flask_wtf.file.FileField("Soubor")
typ = wtforms.SelectField(
"Typ dat",
choices=ImportType.choices(), coerce=ImportType.coerce,
default=ImportType.participants,
)
fmt = wtforms.SelectField(
"Formát souboru",
choices=FileFormat.choices(), coerce=FileFormat.coerce,
default=FileFormat.cs_csv,
)
submit = wtforms.SubmitField('Importovat')
get_template = wtforms.SubmitField('Stáhnout šablonu')
class ParticipantsFilterForm(PagerForm):
@@ -263,44 +273,58 @@ def org_contest(id: int, site_id: Optional[int] = None):
)
@app.route('/org/contest/c/<int:id>/import', methods=('GET', 'POST'))
def org_contest_import(id: int):
contest, rr = get_contest_rr(id, Right.manage_contest)
def generic_import(round: db.Round, contest: Optional[db.Contest]):
"""Společná funkce pro importování do soutěží a kol"""
form = ImportForm()
errs = []
if form.validate_on_submit():
tmp_name = secrets.token_hex(16) + '.csv'
fmt = form.fmt.data
imp = create_import(user=g.user, type=form.typ.data, fmt=fmt, round=round, contest=contest)
if form.submit.data:
if form.file.data is not None:
tmp_name = secrets.token_hex(16) + '.' + fmt.get_extension()
tmp_path = os.path.join(app.instance_path, 'imports', tmp_name)
form.file.data.save(tmp_path)
imp = mo.imports.Import(g.user)
if imp.import_contest(contest.round, contest, tmp_path):
flash(f'Účastníci importováni ({imp.cnt_rows} řádků, založeno {imp.cnt_new_users} uživatelů, {imp.cnt_new_participations} účastí)', 'success')
if imp.run(tmp_path):
if imp.cnt_rows == 0:
flash('Soubor neobsahoval žádné řádky s daty', 'danger')
else:
flash(f'Importováno ({imp.cnt_rows} řádků, založeno {imp.cnt_new_users} uživatelů, {imp.cnt_new_participations} účastí, {imp.cnt_new_roles} rolí)', 'success')
if contest is not None:
return redirect(url_for('org_contest', id=contest.contest_id))
else:
flash('Došlo k chybě při importu (detaily níže)', 'danger')
return redirect(url_for('org_round', id=round.round_id))
else:
errs = imp.errors
else:
flash('Vyberte si prosím soubor', 'danger')
elif form.get_template.data:
out = imp.get_template()
resp = app.make_response(out)
resp.content_type = fmt.get_content_type()
resp.headers.add('Content-Disposition', 'attachment; filename=OSMO-' + imp.template_basename + '.' + fmt.get_extension())
return resp
return render_template(
'org_contest_import.html',
'org_generic_import.html',
contest=contest,
round=round,
form=form,
errs=errs,
)
@app.route('/doc/import_contest')
def doc_import_contest():
return render_template('doc_import_contest.html')
@app.route('/doc/import')
def doc_import():
return render_template('doc_import.html')
@app.route('/org/contest/import/sablona.csv')
def org_contest_import_template():
out = mo.imports.contest_template()
resp = app.make_response(out)
resp.content_type = 'text/csv; charset=utf=8'
return resp
@app.route('/org/contest/c/<int:id>/import', methods=('GET', 'POST'))
def org_contest_import(id: int):
contest, rr = get_contest_rr(id, Right.manage_contest)
return generic_import(contest.round, contest)
@app.route('/org/contest/c/<int:id>/ucastnici', methods=('GET', 'POST'))
@@ -627,87 +651,6 @@ def org_submit_paper(contest_id: int, paper_id: int, filename: str, site_id: Opt
return mo.web.util.send_task_paper(paper)
@app.route('/org/contest/c/<int:id>/proctor-import', methods=('GET', 'POST'))
def org_proctor_import(id: int):
contest, rr = get_contest_rr(id, Right.manage_contest)
form = ImportForm()
errs = []
if form.validate_on_submit():
tmp_name = secrets.token_hex(16) + '.csv'
tmp_path = os.path.join(app.instance_path, 'imports', tmp_name)
form.file.data.save(tmp_path)
imp = mo.imports.Import(g.user)
if imp.import_proctors(contest.round, tmp_path):
flash(f'Dozor importován ({imp.cnt_rows} řádků, založeno {imp.cnt_new_users} uživatelů, {imp.cnt_new_roles} rolí)', 'success')
return redirect(url_for('org_contest', id=contest.contest_id))
else:
flash('Došlo k chybě při importu (detaily níže)', 'danger')
errs = imp.errors
return render_template(
'org_proctor_import.html',
contest=contest,
form=form,
errs=errs,
)
@app.route('/org/contest/import/sablona-dozor.csv')
def org_proctor_import_template():
out = mo.imports.proctor_template()
resp = app.make_response(out)
resp.content_type = 'text/csv; charset=utf=8'
return resp
@app.route('/doc/import-dozor')
def org_proctor_import_help():
return render_template('doc_import_proctor.html')
@app.route('/org/contest/c/<int:id>/judge-import', methods=('GET', 'POST'))
def org_judge_import(id: int):
contest, rr = get_contest_rr(id, Right.manage_contest)
form = ImportForm()
errs = []
if form.validate_on_submit():
# FIXME: Tohle je ošklivě repetitivní. Až začne importů přibývat, nutno vyřešit lépe.
tmp_name = secrets.token_hex(16) + '.csv'
tmp_path = os.path.join(app.instance_path, 'imports', tmp_name)
form.file.data.save(tmp_path)
imp = mo.imports.Import(g.user)
if imp.import_judges(contest.round, contest, tmp_path):
flash(f'Opravovatelé importováni ({imp.cnt_rows} řádků, založeno {imp.cnt_new_users} uživatelů, {imp.cnt_new_roles} rolí)', 'success')
return redirect(url_for('org_contest', id=contest.contest_id))
else:
flash('Došlo k chybě při importu (detaily níže)', 'danger')
errs = imp.errors
return render_template(
'org_judge_import.html',
contest=contest,
form=form,
errs=errs,
)
@app.route('/org/contest/import/sablona-opravovatele.csv')
def org_judge_import_template():
out = mo.imports.judge_template()
resp = app.make_response(out)
resp.content_type = 'text/csv; charset=utf=8'
return resp
@app.route('/doc/import-opravovatele')
def org_judge_import_help():
return render_template('doc_import_judge.html')
def get_solutions_query(
task: db.Task,
for_contest: Optional[db.Contest] = None,
Loading