update endpoints for download and upload students list in csv file
This commit is contained in:
parent
247dfe3f31
commit
0722eb9648
@ -80,7 +80,7 @@ def create_group(year_group_id: int, data: dict) -> dict:
|
||||
return {"message": "Group was created!"}
|
||||
|
||||
|
||||
@bp.get("/<int:id>/")
|
||||
@bp.get("/<int:id>/detail/")
|
||||
@bp.output(GroupSchema)
|
||||
def detail_group(id: int) -> Group:
|
||||
group = Group.query.filter_by(id=id).first()
|
||||
|
@ -3,12 +3,12 @@ from itertools import islice
|
||||
|
||||
from flask import Response, abort
|
||||
from apiflask import APIBlueprint
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
from sqlalchemy import or_
|
||||
from flask_sqlalchemy import get_debug_queries
|
||||
|
||||
from ...students.models import Student, Group, YearGroup, YearGroupStudents
|
||||
from ...project_supervisor.models import ProjectSupervisor
|
||||
from ..schemas import StudentSchema, StudentEditSchema, StudentsPaginationSchema, \
|
||||
from ..schemas import StudentSchema, StudentEditSchema, StudentsPaginationSchema, YearGroupInfoQuery, \
|
||||
StudentCreateSchema, MessageSchema, FileSchema, StudentQuerySchema, StudentListFileDownloaderSchema
|
||||
from ...dependencies import db
|
||||
from ..utils import parse_csv, generate_csv
|
||||
@ -109,27 +109,49 @@ def create_student(data: dict) -> dict:
|
||||
|
||||
|
||||
@bp.post("/upload/")
|
||||
@bp.input(YearGroupInfoQuery, location='query')
|
||||
@bp.input(FileSchema, location='form_and_files')
|
||||
@bp.output(MessageSchema)
|
||||
def upload_students(file: dict) -> dict:
|
||||
def upload_students(query: dict, file: dict) -> dict:
|
||||
"""Add only Students to chosen year group if students exist in db and assigned to correct year group,
|
||||
they will be omitted"""
|
||||
year_group_id = query.get('id')
|
||||
yg = YearGroup.query.filter(YearGroup.id == year_group_id).first()
|
||||
if yg is None:
|
||||
abort(404, "Not found year group!")
|
||||
|
||||
uploaded_file = file.get('file')
|
||||
if uploaded_file and is_allowed_extensions(uploaded_file.filename):
|
||||
try:
|
||||
students = parse_csv(uploaded_file, mode=True)
|
||||
students = parse_csv(uploaded_file)
|
||||
while True:
|
||||
sliced_students = islice(students, 5)
|
||||
list_of_students = list(sliced_students)
|
||||
|
||||
if len(list_of_students) == 0:
|
||||
break
|
||||
db.session.add_all(list_of_students)
|
||||
|
||||
students_in_db = Student.query.filter(or_(Student.index == s.index for s in list_of_students)).all()
|
||||
students_in_db_and_assigned_to_year_group = Student.query.join(YearGroupStudents, isouter=True). \
|
||||
filter(YearGroupStudents.year_group_id == year_group_id). \
|
||||
filter(or_(Student.index == s.index for s in list_of_students)).all()
|
||||
|
||||
student_index_in_db = [s.index for s in students_in_db]
|
||||
student_index_in_year_group = [s.index for s in students_in_db_and_assigned_to_year_group]
|
||||
students_in_db_and_not_assigned_to_year_group = list(
|
||||
filter(lambda s: s.index not in student_index_in_year_group, students_in_db))
|
||||
|
||||
students_not_exists_in_db = list(filter(lambda s: s.index not in student_index_in_db, list_of_students))
|
||||
db.session.add_all(students_not_exists_in_db)
|
||||
db.session.commit()
|
||||
|
||||
ygs = [YearGroupStudents(year_group_id=year_group_id, student_index=student.index) for student in
|
||||
students_in_db_and_not_assigned_to_year_group + students_not_exists_in_db]
|
||||
db.session.add_all(ygs)
|
||||
db.session.commit()
|
||||
|
||||
except InvalidNameOrTypeHeaderException:
|
||||
abort(400, "Invalid format of csv file!")
|
||||
except IntegrityError as e:
|
||||
# in the future create sql query checks index and add only these students, which didn't exist in db
|
||||
abort(400, "These students have already exist!")
|
||||
|
||||
else:
|
||||
abort(400, "Invalid extension of file")
|
||||
|
||||
@ -139,14 +161,15 @@ def upload_students(file: dict) -> dict:
|
||||
@bp.post("/download/")
|
||||
@bp.input(StudentListFileDownloaderSchema, location='query')
|
||||
def download_students(query: dict) -> Response:
|
||||
mode = query.get('mode')
|
||||
mode = mode if mode is not None else True
|
||||
students = db.session.query(Student).join(Group). \
|
||||
join(ProjectSupervisor).filter(Student.mode == mode).all()
|
||||
year_group_id = query.get('year_group_id')
|
||||
students_and_groups = db.session.query(Student, Group).join(Group, Student.groups). \
|
||||
filter(Group.year_group_id == year_group_id). \
|
||||
join(ProjectSupervisor).all()
|
||||
|
||||
if len(students) == 0:
|
||||
if len(students_and_groups) == 0:
|
||||
abort(404, "Not found students, which are assigned to group!")
|
||||
csv_file = generate_csv(students)
|
||||
|
||||
csv_file = generate_csv(students_and_groups)
|
||||
response = Response(csv_file, mimetype='text/csv')
|
||||
response.headers.set("Content-Disposition", "attachment", filename="students_list.csv")
|
||||
return response
|
||||
|
@ -6,5 +6,5 @@ from .project_supervisor import ProjectSupervisorQuerySchema, ProjectSupervisors
|
||||
ProjectSupervisorCreateSchema, ProjectSupervisorEditSchema, ProjectSupervisorYearGroupSchema
|
||||
from .students import ProjectSupervisorSchema, GroupSchema, StudentSchema, StudentsPaginationSchema, \
|
||||
StudentListFileDownloaderSchema, StudentCreateSchema, StudentEditSchema, MessageSchema, FileSchema, \
|
||||
StudentQuerySchema
|
||||
StudentQuerySchema, YearGroupInfoQuery
|
||||
from .year_group import YearGroupSchema, YearGroupPaginationSchema, YearGroupQuerySchema
|
||||
|
@ -1,4 +1,4 @@
|
||||
from marshmallow import fields, validate
|
||||
from marshmallow import fields, validate, Schema
|
||||
|
||||
from ...dependencies import ma
|
||||
from ...students.models import Student, Group
|
||||
@ -32,7 +32,7 @@ class StudentsPaginationSchema(ma.Schema):
|
||||
|
||||
|
||||
class StudentListFileDownloaderSchema(ma.Schema):
|
||||
mode = fields.Integer()
|
||||
year_group_id = fields.Integer(required=True)
|
||||
|
||||
|
||||
class StudentCreateSchema(ma.Schema):
|
||||
@ -64,3 +64,7 @@ class StudentQuerySchema(ma.Schema):
|
||||
order_by_last_name = fields.Str()
|
||||
page = fields.Integer()
|
||||
per_page = fields.Integer()
|
||||
|
||||
|
||||
class YearGroupInfoQuery(Schema):
|
||||
id = fields.Integer(required=True)
|
||||
|
@ -2,7 +2,7 @@ import datetime
|
||||
from collections import defaultdict
|
||||
from io import BytesIO
|
||||
from itertools import chain
|
||||
from typing import Generator, Any, List
|
||||
from typing import Generator, Any, List, Tuple
|
||||
|
||||
import pandas as pd
|
||||
from reportlab.lib import colors
|
||||
@ -10,10 +10,10 @@ from reportlab.lib.enums import TA_CENTER
|
||||
from reportlab.lib.styles import getSampleStyleSheet
|
||||
from reportlab.lib.units import mm, inch
|
||||
from reportlab.platypus import SimpleDocTemplate, Paragraph, PageBreak, Table
|
||||
from werkzeug.datastructures import FileStorage
|
||||
|
||||
from .exceptions import InvalidNameOrTypeHeaderException
|
||||
from ..students.models import Student
|
||||
# from ..examination_schedule.models import Enrollment
|
||||
from ..students.models import Student, Group
|
||||
|
||||
|
||||
def check_columns(df: pd.DataFrame) -> bool:
|
||||
@ -34,7 +34,7 @@ def check_columns(df: pd.DataFrame) -> bool:
|
||||
return flag
|
||||
|
||||
|
||||
def parse_csv(file, mode) -> Generator[Student, Any, None]:
|
||||
def parse_csv(file: FileStorage) -> Generator[Student, Any, None]:
|
||||
df = pd.read_csv(file)
|
||||
|
||||
if not check_columns(df):
|
||||
@ -45,18 +45,17 @@ def parse_csv(file, mode) -> Generator[Student, Any, None]:
|
||||
index=dict(item.items())['INDEKS'],
|
||||
pesel=str(int(dict(item.items())['PESEL'])) if not pd.isna(
|
||||
dict(item.items())['PESEL']) else None,
|
||||
email=dict(item.items())['EMAIL'],
|
||||
mode=mode)
|
||||
email=dict(item.items())['EMAIL'])
|
||||
for _, item in df.iterrows())
|
||||
|
||||
return students
|
||||
|
||||
|
||||
def generate_csv(students: List[Student]) -> str:
|
||||
def generate_csv(students_and_groups: List[Tuple[Student, Group]]) -> str:
|
||||
headers = ['PESEL', 'INDEKS', 'IMIE', 'NAZWISKO', 'EMAIL', 'CDYD_KOD', 'PRZ_KOD', 'TZAJ_KOD', 'GR_NR', 'PRG_KOD']
|
||||
data = [(student.pesel, student.index, student.first_name, student.last_name, student.email,
|
||||
student.group.cdyd_kod, student.group.prz_kod, student.group.tzaj_kod, student.group.project_supervisor_id,
|
||||
None) for student in students]
|
||||
group.cdyd_kod, group.prz_kod, group.tzaj_kod, group.project_supervisor_id,
|
||||
None) for student, group in students_and_groups]
|
||||
dataframe = defaultdict(list)
|
||||
for row in data:
|
||||
for idx, item in enumerate(row):
|
||||
|
Loading…
Reference in New Issue
Block a user