A simple implementation to define a set of courses taught to students at a given level. This concept is implemented by linking a level within a schoolyear to a course in the same schoolyear.
Ability to define a student’s level, as well as any UI whatsoever, are not implemented yet, so levels are pretty useless at this point.
There is a root container, initialized on application startup:
>>> from schooltool.app.interfaces import ISchoolToolApplication
>>> from schooltool.app.interfaces import ApplicationInitializationEvent
>>> from schooltool.app.main import initializeSchoolToolPlugins
>>> app = ISchoolToolApplication(None)
>>> initializeSchoolToolPlugins(ApplicationInitializationEvent(app))
>>> sorted(app.keys())
['schooltool.level.level', 'schooltool.schoolyear']
>>> app['schooltool.level.level']
<schooltool.level.level.LevelContainerContainer ...>
Sets of levels are stored in it for every school year. Levels do not work without active school year.
>>> from schooltool.level.interfaces import ILevelContainer
>>> print ILevelContainer(app, None)
None
When application has an active schoolyear, you can adapt it to ILevelContainer to get the relevant levels:
>>> from schooltool.schoolyear.interfaces import ISchoolYearContainer
>>> schoolyears = ISchoolYearContainer(app)
>>> from datetime import date
>>> from schooltool.schoolyear.schoolyear import SchoolYear
>>> schoolyears['2005'] = SchoolYear(
... "2005", date(2005, 9, 1), date(2005, 12, 30))
>>> print schoolyears.getActiveSchoolYear().title
2005
>>> print ILevelContainer(app, None)
<schooltool.level.level.LevelContainer ...>
Of course, you can obtain the level container directly from a school year:
>>> schoolyears['2006'] = SchoolYear(
... "2006", date(2006, 9, 1), date(2006, 12, 30))
>>> print ILevelContainer(schoolyears['2006'], None)
<schooltool.level.level.LevelContainer ...>
>>> bool(ILevelContainer(schoolyears['2005']) is
... ILevelContainer(schoolyears['2006']))
False
Levels themselves are simple objects with a title:
>>> from schooltool.level.level import Level
>>> levels_2005 = ILevelContainer(schoolyears['2005'])
>>> levels_2005['2'] = Level(u'Second-years 2005')
>>> levels_2005['1'] = Level(u'First-years 2005')
>>> levels_2006 = ILevelContainer(schoolyears['2006'])
>>> levels_2006['1'] = Level(u'First-years 2006')
>>> [level.title
... for level in ILevelContainer(schoolyears['2005']).values()]
[u'Second-years 2005', u'First-years 2005']
>>> [level.title
... for level in ILevelContainer(schoolyears['2006']).values()]
[u'First-years 2006']
Level containers are ordered:
>>> ILevelContainer(schoolyears['2005']).updateOrder(['1', '2'])
>>> [level.title
... for level in ILevelContainer(schoolyears['2005']).values()]
[u'First-years 2005', u'Second-years 2005']
Levels are linked to courses via schooltool.relationship. There is a helper attribute to manage the relationships:
>>> math = CourseStub('Math')
>>> level_1_2005 = ILevelContainer(schoolyears['2005'])['1']
>>> level_1_2005.courses.add(math)
>>> level_1_2006 = ILevelContainer(schoolyears['2006'])['1']
>>> level_1_2006.courses.add(math)
>>> from schooltool.level.level import URILevelCourses, URILevel
>>> print [level.title
... for level in getRelatedObjects(
... math, URILevel, rel_type=URILevelCourses)]
[u'First-years 2005', u'First-years 2006']
It is important to note that when a school year is deleted, the corresponding level container is also deleted and all level relationships are lost.
>>> top_level_container = ILevelContainer(schoolyears['2005']).__parent__
>>> len(top_level_container)
2
>>> del schoolyears['2006']
>>> len(top_level_container)
1
>>> print [level.title
... for level in getRelatedObjects(
... math, URILevel, rel_type=URILevelCourses)]
[u'First-years 2005']
If you need a dropdown of levels in a form, there is a special level vocabulary.
>>> from zope.schema import Choice
>>> levels_field = Choice(
... title=u"Levels",
... vocabulary='schooltool.level.level.levelvocabulary')
It works with contexts adaptable to ISchoolYear:
>>> context = schoolyears['2005']
>>> levels = levels_field.bind(context)
>>> for term in levels.vocabulary:
... print '%s: %s' % (term.token, term.title)
1-: First-years 2005
2-: Second-years 2005
>>> from zope.interface.verify import verifyObject
>>> from zope.schema.interfaces import IVocabularyTokenized
>>> verifyObject(IVocabularyTokenized, levels.vocabulary)
True