diff --git a/zesje/api.py b/zesje/api.py index 54496c500b4dbf6e0418bf83c19e746e56ff607e..61594fff4f0895f4d33d1ebcbb264195da70d34b 100644 --- a/zesje/api.py +++ b/zesje/api.py @@ -39,6 +39,8 @@ api.add_resource(Feedback, '/feedback/<int:problem_id>') # Other resources that don't return JSON # It is possible to get flask_restful to work with these, but not # very idiomatic. + +# Images api_bp.add_url_rule( '/images/signature/<int:exam_id>/<int:submission_id>', 'signature', @@ -55,8 +57,14 @@ api_bp.add_url_rule( summary_plot.get, ) +# Exports api_bp.add_url_rule( '/export/full', 'full_export', export.full, ) +api_bp.add_url_rule( + '/export/dataframe/<int:exam_id>', + 'dataframe_export', + export.dataframe, +) diff --git a/zesje/helpers/db_helper.py b/zesje/helpers/db_helper.py index d22e59506ff684df7668be1c5c75e39bd8e6bd3f..66d085a4904ecc6fd73f4fc86cc6b82aaf9a6377 100644 --- a/zesje/helpers/db_helper.py +++ b/zesje/helpers/db_helper.py @@ -68,7 +68,10 @@ def solution_data(exam_id, student_id): def full_exam_data(exam_id): """Compute all grades of an exam as a pandas DataFrame.""" with orm.db_session: - students = sorted(Exam[exam_id].submissions.student.id) + exam = Exam[exam_id] + if exam is None: + raise KeyError("No such exam.") + students = sorted(exam.submissions.student.id) data = [solution_data(exam_id, student_id) for student_id in students] diff --git a/zesje/resources/export.py b/zesje/resources/export.py index 2cbf09761829421f724ec7c5103fdf088058eef9..6b2f01052e9e90801a276a9e8e98ea447f68f20f 100644 --- a/zesje/resources/export.py +++ b/zesje/resources/export.py @@ -21,3 +21,26 @@ def full(): resp.headers.set('Content-Disposition', 'attachment', filename='course.sqlite') return resp + + +def dataframe(exam_id): + """Export exam data as a pandas dataframe + + Parameters + ---------- + exam_id : int + + Returns + ------- + exam.pd : pickled pandas dataframe + """ + try: + data = db_helper.full_exam_data(exam_id) + except KeyError: + abort(404) + serialized = BytesIO() + data.to_pickle(serialized) + resp = Response(serialized.getvalue(), 200) + resp.headers.set('Content-Disposition', 'attachment', + filename='exam.pd') + return resp