2021-06-02 21:43:41 +00:00
from flask import flash , request , url_for
2021-04-27 13:50:03 +00:00
from flask_admin . contrib . sqla . filters import BaseSQLAFilter
2021-06-02 21:43:41 +00:00
from flask_admin . menu import MenuLink
2021-07-01 14:38:37 +00:00
from flask_admin . model . template import EndpointLinkRowAction
2021-06-09 00:51:26 +00:00
from flask_security import current_user , hash_password
2021-06-14 10:50:09 +00:00
from sqlalchemy import func
2021-06-30 19:58:57 +00:00
from wtforms import Form , BooleanField , SelectField , TextField , RadioField , FloatField
from wtforms . validators import DataRequired , Email , Optional
from flask_admin . contrib . sqla . fields import QuerySelectMultipleField , QuerySelectField
from flask_admin . helpers import get_form_data
2021-07-01 11:12:43 +00:00
from wtforms . fields . html5 import DateField
2021-04-24 10:05:58 +00:00
2021-06-02 21:43:41 +00:00
from advlabdb import admin , app , db , user_datastore
2021-06-01 23:56:49 +00:00
from advlabdb . configUtils import getConfig
2021-06-02 21:43:41 +00:00
from advlabdb . customClasses import SecureModelView
from advlabdb . models import (
Appointment ,
Assistant ,
Experiment ,
ExperimentMark ,
Group ,
GroupExperiment ,
Part ,
2021-07-01 12:41:20 +00:00
SemesterExperiment ,
2021-06-02 21:43:41 +00:00
PartStudent ,
Role ,
Semester ,
Student ,
User ,
)
from advlabdb . utils import (
partFromLabelInUserActiveSemester ,
randomPassword ,
2021-06-25 23:59:21 +00:00
setUserActiveSemester ,
2021-06-02 21:43:41 +00:00
userActiveSemester ,
)
2021-04-26 19:31:15 +00:00
2021-06-30 20:04:33 +00:00
class UserView ( SecureModelView ) :
2021-04-24 10:05:58 +00:00
column_list = [ " email " , " active " , " roles " , " assistant " ]
column_searchable_list = [ " email " ]
column_filters = [ " active " ]
2021-04-27 21:28:47 +00:00
form_columns = [ " email " , " active " , " roles " ]
2021-07-01 11:12:43 +00:00
column_editable_list = [ " active " ]
2021-04-27 21:28:47 +00:00
form_args = {
" email " : { " validators " : [ Email ( ) ] } ,
" active " : { " default " : True } ,
2021-06-02 21:43:41 +00:00
" roles " : { " validators " : [ DataRequired ( message = " A role is required! " ) ] } ,
2021-04-27 21:28:47 +00:00
}
2021-04-24 10:05:58 +00:00
2021-06-09 00:22:37 +00:00
deleteSelfException = " Tried to delete yourself as user! "
deactivateSelfException = " Tried to deactiavte yourself as user! "
2021-04-24 10:05:58 +00:00
def create_model ( self , form ) :
password = randomPassword ( )
passwordHash = hash_password ( password )
email = form . email . data . lower ( )
roles = [ role . name for role in form . roles . data ]
if " admin " in roles :
flash ( " You have registered a new admin! " , " danger " )
2021-06-08 23:07:02 +00:00
try :
model = user_datastore . create_user ( email = email , password = passwordHash , roles = roles )
2021-06-30 19:58:57 +00:00
self . on_model_change ( form , model , True )
2021-06-08 23:07:02 +00:00
self . session . commit ( )
except Exception as ex :
flash ( ex , " error " )
self . session . rollback ( )
else :
flash (
f " { email } registered with roles: { ' , ' . join ( [ role . name for role in form . roles . data ] ) } . " ,
category = " success " ,
)
flash ( f " Random password: { password } " , category = " warning " )
return model
2021-04-24 10:05:58 +00:00
2021-06-09 00:22:37 +00:00
def on_model_delete ( self , model ) :
if model == current_user :
raise Exception ( self . deleteSelfException )
def on_model_change ( self , form , model , is_created ) :
if model == current_user and not form . active . data :
raise Exception ( self . deactivateSelfException )
def handle_view_exception ( self , exc ) :
if exc . args [ 0 ] in ( self . deleteSelfException , self . deactivateSelfException ) :
pass
else :
return super ( ) . handle_view_exception ( exc )
2021-04-24 10:05:58 +00:00
2021-06-30 20:04:33 +00:00
class RoleView ( SecureModelView ) :
2021-06-09 00:22:37 +00:00
can_create = False
can_edit = False
can_delete = False
column_display_actions = False
column_list = [ " name " , " description " ]
2021-04-24 10:05:58 +00:00
2021-04-24 11:38:03 +00:00
2021-06-30 20:04:33 +00:00
class SemesterView ( SecureModelView ) :
2021-06-08 23:07:02 +00:00
can_edit = False
2021-04-24 11:38:03 +00:00
column_list = [ " label " , " parts " ]
2021-07-01 12:41:20 +00:00
form_columns = [ " semester_label " , " year " , " transfer_parts " , " transfer_semester_experiments " , " transfer_assistants " ]
2021-04-24 11:38:03 +00:00
2021-06-08 23:07:02 +00:00
semesterLabels = [ " WS " , " SS " ]
2021-07-01 14:38:37 +00:00
transferDesciption = " Will be trasfered from your current semester. "
2021-04-24 11:38:03 +00:00
form_extra_fields = {
2021-06-25 23:59:21 +00:00
" semester_label " : RadioField (
2021-06-08 23:07:02 +00:00
" Semester " , choices = list ( zip ( semesterLabels , semesterLabels ) ) , validators = [ DataRequired ( ) ]
) ,
" year " : TextField ( " Year " , validators = [ DataRequired ( ) ] ) ,
2021-07-01 12:41:20 +00:00
" transfer_parts " : BooleanField (
2021-07-01 14:38:37 +00:00
" Transfer parts " ,
description = transferDesciption ,
2021-06-25 23:59:21 +00:00
default = True ,
) ,
2021-07-01 12:41:20 +00:00
" transfer_semester_experiments " : BooleanField (
2021-07-01 14:38:37 +00:00
" Transfer Semester Experiemnts " , description = transferDesciption , default = True
) ,
" transfer_assistants " : BooleanField (
" Transfer Assistants " ,
description = transferDesciption + " This option has no effect if Semester Experiments are not transfered. " ,
default = True ,
2021-07-01 12:41:20 +00:00
) ,
2021-04-24 11:38:03 +00:00
}
2021-06-08 23:07:02 +00:00
def create_model ( self , form ) :
try :
model = Semester ( label = form . semester_label . data + form . year . data )
2021-06-30 19:58:57 +00:00
2021-06-08 23:07:02 +00:00
self . session . add ( model )
2021-06-30 19:58:57 +00:00
self . on_model_change ( form , model , True )
2021-06-08 23:07:02 +00:00
self . session . commit ( )
except Exception as ex :
flash ( ex , " error " )
self . session . rollback ( )
else :
self . after_model_change ( form , model , True )
return model
2021-04-24 11:38:03 +00:00
def after_model_change ( self , form , model , is_created ) :
2021-06-25 23:59:21 +00:00
admin . add_link (
MenuLink (
name = model . label ,
url = url_for ( " set_semester " ) + " ?semester_id= " + str ( model . id ) ,
category = " Active semester " ,
)
)
2021-07-01 12:41:20 +00:00
oldSemester = userActiveSemester ( )
2021-06-25 23:59:21 +00:00
setUserActiveSemester ( model . id )
2021-07-01 20:20:34 +00:00
try :
if form . transfer_parts . data :
model . transferPartsFrom ( oldSemester )
2021-04-24 11:38:03 +00:00
2021-07-01 20:20:34 +00:00
if form . transfer_semester_experiments . data :
2021-07-01 12:41:20 +00:00
for semesterExperiment in oldSemester . semester_experiments :
newSemesterExperiment = SemesterExperiment (
experiment = semesterExperiment . experiment , semester = userActiveSemester ( )
)
if form . transfer_assistants . data :
newSemesterExperiment . assistants = semesterExperiment . assistants
self . session . add ( newSemesterExperiment )
2021-06-25 23:59:21 +00:00
2021-07-01 20:20:34 +00:00
self . session . commit ( )
except Exception as ex :
flash ( ex , " error " )
self . session . rollback ( )
2021-05-18 12:54:30 +00:00
2021-04-24 11:38:03 +00:00
2021-06-30 20:04:33 +00:00
class PartView ( SecureModelView ) :
2021-04-24 11:38:03 +00:00
can_view_details = True
2021-07-01 12:41:20 +00:00
column_details_list = [ " label " , " semester " , " part_students " , " groups " ]
2021-04-24 11:38:03 +00:00
form_columns = [ " label " , " semester " ]
2021-06-10 01:14:30 +00:00
def get_query ( self ) :
return super ( ) . get_query ( ) . filter ( Part . id . in_ ( [ part . id for part in userActiveSemester ( ) . parts ] ) )
def get_count_query ( self ) :
return (
self . session . query ( func . count ( " * " ) )
. select_from ( self . model )
. filter ( Part . id . in_ ( [ part . id for part in userActiveSemester ( ) . parts ] ) )
)
2021-04-27 13:50:03 +00:00
2021-06-30 20:04:33 +00:00
class StudentView ( SecureModelView ) :
2021-04-26 19:31:15 +00:00
can_view_details = True
2021-06-30 19:58:57 +00:00
2021-05-14 16:53:15 +00:00
column_list = [ " student_number " , " first_name " , " last_name " , " uni_email " , " contact_email " , " part_students " ]
2021-04-26 22:26:11 +00:00
column_details_list = column_list + [ " bachelor_thesis " , " bachelor_thesis_work_group " , " note " ]
2021-06-30 19:58:57 +00:00
column_sortable_list = [ " student_number " , " first_name " , " last_name " ]
column_searchable_list = column_sortable_list + [ " uni_email " , " contact_email " ]
form_excluded_columns = [ " part_students " ]
2021-04-26 22:26:11 +00:00
2021-04-27 21:28:47 +00:00
form_args = {
2021-05-14 16:53:15 +00:00
" uni_email " : { " validators " : [ Email ( ) ] } ,
" contact_email " : { " validators " : [ Email ( ) ] } ,
2021-04-27 21:28:47 +00:00
}
2021-07-01 14:38:37 +00:00
column_extra_row_actions = [
EndpointLinkRowAction (
" glyphicon glyphicon-time " ,
id_arg = " flt1_0 " ,
title = " Experiments history " ,
endpoint = " experimentmark.index_view " ,
)
]
2021-06-10 01:14:30 +00:00
2021-06-30 19:58:57 +00:00
def partQueryFactory ( ) :
return Part . query . filter ( Part . id . in_ ( [ part . id for part in userActiveSemester ( ) . parts ] ) )
2021-06-10 01:14:30 +00:00
2021-07-01 11:12:43 +00:00
def groupQueryFactory ( ) :
return Group . query . filter ( Group . part_id . in_ ( [ part . id for part in userActiveSemester ( ) . parts ] ) )
2021-06-30 20:04:33 +00:00
class PartStudentView ( SecureModelView ) :
2021-06-30 19:58:57 +00:00
class CreateForm ( Form ) :
def studentQueryFactory ( ) :
return Student . query
2021-04-26 22:26:11 +00:00
2021-06-30 19:58:57 +00:00
student = QuerySelectField (
" Student " , query_factory = studentQueryFactory , validators = [ DataRequired ( ) ] , allow_blank = True , blank_text = " - "
)
part = QuerySelectField (
" Part " , query_factory = partQueryFactory , validators = [ DataRequired ( ) ] , allow_blank = True , blank_text = " - "
)
group = QuerySelectField ( " Group " , query_factory = groupQueryFactory , allow_blank = True , blank_text = " - " )
2021-04-26 22:26:11 +00:00
2021-06-30 19:58:57 +00:00
class EditForm ( CreateForm ) :
student = None
part = None
final_part_mark = FloatField ( " Final Part Mark " , validators = [ Optional ( ) ] )
2021-06-08 23:07:02 +00:00
2021-06-30 19:58:57 +00:00
form = EditForm
2021-06-08 23:07:02 +00:00
2021-06-30 19:58:57 +00:00
column_filters = [ " part " , " student " , " group " ]
2021-04-26 19:31:15 +00:00
2021-06-30 19:58:57 +00:00
partGroupPartMismatchException = " Part and groups part don ' t match! "
2021-04-26 19:31:15 +00:00
2021-06-30 19:58:57 +00:00
def create_form ( self , obj = None ) :
form = self . CreateForm
return form ( get_form_data ( ) , obj = obj )
2021-04-27 21:28:47 +00:00
2021-06-30 19:58:57 +00:00
def on_model_change ( self , form , model , is_created ) :
if model . group and model . part != model . group . part :
raise Exception ( self . partGroupPartMismatchException )
2021-04-27 21:28:47 +00:00
2021-06-30 19:58:57 +00:00
def handle_view_exception ( self , exc ) :
if exc . args [ 0 ] in ( self . partGroupPartMismatchException ) :
pass
2021-04-27 21:28:47 +00:00
else :
2021-06-30 19:58:57 +00:00
return super ( ) . handle_view_exception ( exc )
2021-04-27 21:28:47 +00:00
2021-06-10 01:14:30 +00:00
def get_query ( self ) :
return super ( ) . get_query ( ) . filter ( PartStudent . part_id . in_ ( [ part . id for part in userActiveSemester ( ) . parts ] ) )
def get_count_query ( self ) :
return (
self . session . query ( func . count ( " * " ) )
. select_from ( self . model )
. filter ( PartStudent . part_id . in_ ( [ part . id for part in userActiveSemester ( ) . parts ] ) )
)
2021-04-27 13:50:03 +00:00
2021-06-30 20:04:33 +00:00
class GroupView ( SecureModelView ) :
2021-06-30 19:58:57 +00:00
class CreateForm ( Form ) :
def partStudentsQueryFactory ( ) :
return PartStudent . query . filter ( PartStudent . part_id . in_ ( [ part . id for part in userActiveSemester ( ) . parts ] ) )
part = QuerySelectField (
2021-07-01 11:12:43 +00:00
" Part " , query_factory = partQueryFactory , validators = [ DataRequired ( ) ] , allow_blank = True , blank_text = " - "
2021-06-30 19:58:57 +00:00
)
2021-07-01 11:12:43 +00:00
part_students = QuerySelectMultipleField ( " Part Students " , query_factory = partStudentsQueryFactory )
2021-06-30 19:58:57 +00:00
class EditForm ( CreateForm ) :
part = None
form = EditForm
2021-07-01 20:20:34 +00:00
column_list = [ " number " , " part " , " part_students " , " group_experiments " ]
2021-07-01 11:12:43 +00:00
column_filters = [ " number " , " part " ]
2021-06-30 19:58:57 +00:00
partStudentPartPartMismatchException = " Part and StudentParts part don ' t match! "
def create_model ( self , form ) :
try :
orderedPartGroups = Group . query . filter ( Group . part == form . part . data ) . order_by ( Group . number )
lastTakenGroupNumber = orderedPartGroups [ - 1 ] . number if orderedPartGroups . count ( ) > 0 else 0
model = Group (
number = lastTakenGroupNumber + 1 ,
part_students = form . part_students . data ,
part = form . part . data ,
)
self . session . add ( model )
self . on_model_change ( form , model , True )
self . session . commit ( )
except Exception as ex :
flash ( ex , " error " )
self . session . rollback ( )
else :
self . after_model_change ( form , model , True )
return model
def on_model_change ( self , form , model , is_created ) :
for partStudent in model . part_students :
if model . part != partStudent . part :
raise Exception ( self . partStudentPartPartMismatchException )
def handle_view_exception ( self , exc ) :
if exc . args [ 0 ] in ( self . partStudentPartPartMismatchException ) :
pass
else :
return super ( ) . handle_view_exception ( exc )
def create_form ( self , obj = None ) :
form = self . CreateForm
return form ( get_form_data ( ) , obj = obj )
2021-06-07 15:15:10 +00:00
2021-06-10 01:14:30 +00:00
def get_query ( self ) :
return super ( ) . get_query ( ) . filter ( Group . part_id . in_ ( [ part . id for part in userActiveSemester ( ) . parts ] ) )
def get_count_query ( self ) :
return (
self . session . query ( func . count ( " * " ) )
. select_from ( self . model )
. filter ( Group . part_id . in_ ( [ part . id for part in userActiveSemester ( ) . parts ] ) )
)
2021-06-07 15:15:10 +00:00
2021-06-30 20:04:33 +00:00
class ExperimentView ( SecureModelView ) :
2021-06-21 16:07:18 +00:00
can_view_details = True
column_filters = [ " deprecated " ]
2021-06-21 16:26:38 +00:00
column_list = [ " number " , " name " , " deprecated " ]
2021-07-01 12:41:20 +00:00
class SemesterExperimentView ( SecureModelView ) :
column_list = [ " experiment " , " semester " , " assistants " ]
2021-06-21 16:26:38 +00:00
def get_query ( self ) :
2021-07-01 12:41:20 +00:00
return super ( ) . get_query ( ) . filter ( SemesterExperiment . semester == userActiveSemester ( ) )
2021-06-21 16:26:38 +00:00
def get_count_query ( self ) :
return (
self . session . query ( func . count ( " * " ) )
. select_from ( self . model )
2021-07-01 12:41:20 +00:00
. filter ( SemesterExperiment . semester == userActiveSemester ( ) )
2021-06-21 16:26:38 +00:00
)
2021-06-21 16:07:18 +00:00
2021-06-30 20:04:33 +00:00
class AssistantView ( SecureModelView ) :
2021-06-24 17:24:14 +00:00
can_view_details = True
2021-07-01 12:41:20 +00:00
column_list = [ " first_name " , " last_name " , " email " , " user " , " semester_experiments " ]
2021-07-01 11:12:43 +00:00
column_details_list = column_list + [
" phone_number " ,
" mobile_phone_number " ,
" room " ,
" building " ,
" appointments " ,
" experiment_marks " ,
]
2021-06-24 17:24:14 +00:00
column_filters = [ " user.active " ]
form_excluded_columns = [ " experiment_marks " ]
2021-06-30 20:04:33 +00:00
class GroupExperimentView ( SecureModelView ) :
2021-07-01 11:12:43 +00:00
class CreateForm ( Form ) :
2021-07-01 12:41:20 +00:00
def semesterExperimentQueryFactory ( ) :
return SemesterExperiment . query . filter ( SemesterExperiment . semester == userActiveSemester ( ) )
2021-07-01 11:12:43 +00:00
def assistantQueryFactory ( ) :
return Assistant . query . filter (
Assistant . user_id . in_ ( [ user . id for user in User . query . filter ( User . active == True ) ] )
)
group = QuerySelectField (
" Group " , query_factory = groupQueryFactory , validators = [ DataRequired ( ) ] , allow_blank = True , blank_text = " - "
)
2021-07-01 12:41:20 +00:00
semester_experiment = QuerySelectField (
" Semester Experiment " ,
query_factory = semesterExperimentQueryFactory ,
2021-07-01 11:12:43 +00:00
validators = [ DataRequired ( ) ] ,
allow_blank = True ,
blank_text = " - " ,
)
assistantBlankText = " Auto assign if experiment has only one assistant "
2021-07-01 17:43:59 +00:00
appointment1_date = DateField ( " Appointment-1 Date " , validators = [ Optional ( ) ] )
2021-07-01 14:38:37 +00:00
appointment1_special = BooleanField ( " Appointment-1 special " , default = False )
2021-07-01 11:12:43 +00:00
appointment1_assistant = QuerySelectField (
2021-07-01 14:38:37 +00:00
" Appointment-1 Assistant " ,
2021-07-01 11:12:43 +00:00
query_factory = assistantQueryFactory ,
allow_blank = True ,
blank_text = assistantBlankText ,
)
2021-07-01 17:43:59 +00:00
appointment2_date = DateField ( " Appointment-2 Date " , validators = [ Optional ( ) ] )
2021-07-01 14:38:37 +00:00
appointment2_special = BooleanField ( " Appointment-2 special " , default = False )
2021-07-01 11:12:43 +00:00
appointment2_assistant = QuerySelectField (
2021-07-01 14:38:37 +00:00
" Appointment-2 Assistant " ,
2021-07-01 11:12:43 +00:00
query_factory = assistantQueryFactory ,
allow_blank = True ,
blank_text = assistantBlankText ,
)
form = CreateForm
2021-07-01 14:38:37 +00:00
can_edit = False
2021-07-01 12:41:20 +00:00
column_list = [ " group " , " semester_experiment " , " appointments " , " experiment_marks " ]
column_filters = [ " group " , " semester_experiment.experiment " , " appointments " ]
2021-06-24 17:39:26 +00:00
2021-07-01 17:43:59 +00:00
def create_model ( self , form ) :
try :
2021-07-01 20:20:34 +00:00
model = GroupExperiment . checkAndInit (
semester_experiment = form . semester_experiment . data , group = form . group . data
)
2021-07-01 17:43:59 +00:00
self . session . add ( model )
for appointmentDate , special , assistant in zip (
[ form . appointment1_date . data , form . appointment2_date . data ] ,
[ form . appointment1_special . data , form . appointment2_special . data ] ,
[ form . appointment1_assistant . data , form . appointment2_assistant . data ] ,
) :
if appointmentDate :
if assistant :
if assistant not in form . semester_experiment . data . assistants :
raise Exception ( f " { assistant } not responsible for { form . semester_experiment . data } ! " )
else :
if len ( form . semester_experiment . data . assistants ) != 1 :
raise Exception (
f " Experiment { form . semester_experiment . data } has more than one assistant. You have to assign one of these assistants: { form . semester_experiment . data . assistants } "
)
assistant = form . semester_experiment . data . assistants [ 0 ]
appointment = Appointment (
date = appointmentDate ,
special = special ,
group_experiment = model ,
assistant = assistant ,
)
self . session . add ( appointment )
self . on_model_change ( form , model , True )
self . session . commit ( )
except Exception as ex :
flash ( ex , " error " )
self . session . rollback ( )
else :
2021-07-01 20:20:34 +00:00
if model . appointments :
flash ( f " Appointments { model . appointments } added. " , " success " )
2021-07-01 17:43:59 +00:00
self . after_model_change ( form , model , True )
return model
2021-06-24 17:39:26 +00:00
def get_query ( self ) :
return (
super ( )
. get_query ( )
. filter (
GroupExperiment . group_id . in_ (
[
g . id
for g in Group . query . filter ( Group . part_id . in_ ( [ part . id for part in userActiveSemester ( ) . parts ] ) )
]
)
)
)
def get_count_query ( self ) :
return (
self . session . query ( func . count ( " * " ) )
. select_from ( self . model )
. filter (
GroupExperiment . group_id . in_ (
[
g . id
for g in Group . query . filter ( Group . part_id . in_ ( [ part . id for part in userActiveSemester ( ) . parts ] ) )
]
)
)
)
2021-07-01 11:12:43 +00:00
class AppointmentView ( SecureModelView ) :
column_list = [ " date " , " special " , " group_experiment " , " assistant " ]
2021-07-01 14:38:37 +00:00
class ExperimentMarkView ( SecureModelView ) :
class StudentIdFilter ( BaseSQLAFilter ) :
def apply ( self , query , value , alias = None ) :
return query . filter ( self . column == value )
def operation ( self ) :
return " equals "
def validate ( self , value ) :
if Student . query . get ( value ) :
return True
else :
return False
column_filters = [
StudentIdFilter ( PartStudent . id , " Student / ID " ) ,
" part_student.student " ,
" group_experiment.semester_experiment.semester " ,
" group_experiment.semester_experiment.experiment " ,
2021-07-01 17:43:59 +00:00
" assistant " ,
2021-07-01 14:38:37 +00:00
]
2021-06-30 20:04:33 +00:00
admin . add_view ( StudentView ( Student , db . session ) )
admin . add_view ( PartStudentView ( PartStudent , db . session ) )
admin . add_view ( GroupView ( Group , db . session ) )
admin . add_view ( GroupExperimentView ( GroupExperiment , db . session ) )
2021-07-01 14:38:37 +00:00
admin . add_view ( AppointmentView ( Appointment , db . session ) )
admin . add_view ( ExperimentMarkView ( ExperimentMark , db . session ) )
2021-06-30 20:04:33 +00:00
admin . add_view ( ExperimentView ( Experiment , db . session ) )
2021-07-01 12:41:20 +00:00
admin . add_view ( SemesterExperimentView ( SemesterExperiment , db . session ) )
2021-06-30 20:04:33 +00:00
admin . add_view ( AssistantView ( Assistant , db . session ) )
admin . add_view ( PartView ( Part , db . session ) )
admin . add_view ( SemesterView ( Semester , db . session ) )
admin . add_view ( UserView ( User , db . session ) )
admin . add_view ( RoleView ( Role , db . session ) )
2021-04-18 23:33:46 +00:00
2021-04-24 10:05:58 +00:00
with app . app_context ( ) :
2021-07-01 12:41:20 +00:00
semesters = Semester . query . order_by ( Semester . id )
2021-05-17 14:55:04 +00:00
for semester in semesters :
2021-06-02 21:43:41 +00:00
admin . add_link (
MenuLink (
name = semester . label ,
url = url_for ( " set_semester " ) + " ?semester_id= " + str ( semester . id ) ,
category = " Active semester " ,
)
)
2021-06-28 16:43:13 +00:00
admin . add_link ( MenuLink ( name = " Logout " , url = url_for ( " security.logout " ) ) )