school
(School management)¶
A tested document¶
This is a tested document. The following instructions are used for initialization:
>>> import lino
>>> lino.startup('lino_prima.projects.prima1.settings')
>>> from lino.api.doctest import *
Glossary¶
- enrolment¶
When a given pupil is member of a given group in a given school year.
Class reference¶
- class lino_prima.lib.school.Group¶
Django model to represent a group of pupils working together during an academic year (a class).
- class lino_prima.lib.school.Enrolment¶
Django model to represent an enrolment of a given pupil in a given group.
Subjects, groups and courses¶
>>> rt.show(school.Grades)
...
==== ============== ================== =========== ====================== =================== ========================
ID Designation Designation (de) Reference Certificate template Rating conditions Rating conditions (de)
---- -------------- ------------------ ----------- ---------------------- ------------------- ------------------------
1 First grade First grade 1 Junior
2 Second grade Second grade 2 Junior
3 Third grade Third grade 3 Senior
4 Fourth grade Fourth grade 4 Senior
5 Fifth grade Fifth grade 5 Senior
6 Sixth grade Sixth grade 6 Senior
7 Alumni Alumni X
==== ============== ================== =========== ====================== =================== ========================
The lino.mixins.ref.Referrable.get_next_row()
method returns the “next”
row:
>>> for obj in school.Grade.objects.all():
... print(f"{obj} --> {obj.get_next_row()}")
First grade --> Second grade
Second grade --> Third grade
Third grade --> Fourth grade
Fourth grade --> Fifth grade
Fifth grade --> Sixth grade
Sixth grade --> None
Alumni --> None
The lino.modlib.periods.StoredYear
model has an overridden
lino.mixins.ref.Referrable.get_next_row()
method:
>>> for obj in periods.StoredYear.objects.all():
... print(f"{obj} --> {obj.get_next_row()}")
2023/24 --> 2024/25
2024/25 --> 2025/26
2025/26 --> 2026/27
2026/27 --> 2027/28
2027/28 --> 2028/29
2028/29 --> 2029/30
2029/30 --> None
>>> rt.show(school.Subjects)
...
===== ============= ================== ========== ====== ============= ==================
No. Designation Designation (de) Advanced Icon Rating type Image
----- ------------- ------------------ ---------- ------ ------------- ------------------
1 Science Wissenschaften Yes 🔬
2 French Französisch Yes 🥐 1f347_grapes.png
3 Mathematics Mathematik Yes 🖩
4 German Deutsch Yes 🥨 1f34e_apple.png
5 Religion Religion Yes 🕊
6 Music Musik No 🎜 Predicates
7 Sport Sport No ⛹ Predicates 26bd_soccer.png
8 Art Kunst No 🎨 Smilies
===== ============= ================== ========== ====== ============= ==================
The MyGroups
table shows only groups of the currently opened school
year while Groups
shows them all:
>>> rt.show(school.MyGroups, display_mode="grid")
...
============= ================== ============== =============== ====
Designation Designation (de) Grade Academic year ID
------------- ------------------ -------------- --------------- ----
2A Second grade 2024/25 13
2B Second grade 2024/25 14
3A Third grade 2024/25 15
3B Third grade 2024/25 16
4A Fourth grade 2024/25 17
4B Fourth grade 2024/25 18
5A Fifth grade 2024/25 19
5B Fifth grade 2024/25 20
6A Sixth grade 2024/25 21
6B Sixth grade 2024/25 22
7A Sixth grade 2024/25 23
7B Sixth grade 2024/25 24
============= ================== ============== =============== ====
>>> rt.show(school.AllGroups)
...
============= ================== ============== =============== ====
Designation Designation (de) Grade Academic year ID
------------- ------------------ -------------- --------------- ----
1A First grade 2023/24 1
1B First grade 2023/24 7
2A Second grade 2023/24 2
2A Second grade 2024/25 13
2B Second grade 2023/24 8
2B Second grade 2024/25 14
3A Third grade 2023/24 3
3A Third grade 2024/25 15
3B Third grade 2023/24 9
3B Third grade 2024/25 16
4A Fourth grade 2023/24 4
4A Fourth grade 2024/25 17
4B Fourth grade 2023/24 10
4B Fourth grade 2024/25 18
5A Fifth grade 2023/24 5
5A Fifth grade 2024/25 19
5B Fifth grade 2023/24 11
5B Fifth grade 2024/25 20
6A Sixth grade 2023/24 6
6A Sixth grade 2024/25 21
6B Sixth grade 2023/24 12
6B Sixth grade 2024/25 22
7A Sixth grade 2024/25 23
7B Sixth grade 2024/25 24
============= ================== ============== =============== ====
Lino automatically creates a course for every subject for which there is a section in the certificate template.
>>> grp = school.Group.objects.filter(designation="5B").last()
>>> rt.show(school.CoursesByGroup, grp)
`Science <…>`__, `French <…>`__, `Mathematics <…>`__, `German <…>`__, `Religion <…>`__
>>> grp = school.Group.objects.filter(designation="6A").last()
>>> rt.show(school.CoursesByGroup, grp)
`Science <…>`__, `French <…>`__, `Mathematics <…>`__, `German <…>`__, `Religion <…>`__, `Music <…>`__, `Sport <…>`__, `Art <…>`__
Working with scores¶
>>> settings.SITE.site_locale
'de_BE.UTF-8'
>>> from lino_prima.lib.ratings.utils import ScoreValue, RatingCollector, format_score
>>> v1 = ScoreValue(8, 10)
>>> print(v1)
8/10
>>> print(v1.absolute)
8/10
>>> print(v1.relative)
80 %
>>> print(v1.rebase(20))
16/20
>>> v2 = ScoreValue(5, 20)
>>> print(f"{v1} + {v2} = {v1+v2}")
8/10 + 5/20 = 13/30
>>> tot = v1 + v2
>>> print(tot.relative)
43,3 %
>>> round(100*13/30, 1)
43.3
>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
'en_US.UTF-8'
>>> print(tot.relative)
43.3 %
>>> print(tot)
13/30
>>> print(ScoreValue(5.29, 8))
5.3/8
>>> v3 = ScoreValue(5.24, 8)
>>> print(v3)
5.2/8
>>> print(v3*3)
15.7/24
>>> tot = RatingCollector()
>>> tot.collect(8, 10)
>>> tot.collect(5, 20)
>>> print(tot)
13/30
>>> tot.ratings
[<ScoreValue(8, 10)>, <ScoreValue(5, 20)>]
>>> " + ".join(map(str, tot.ratings))
'8/10 + 5/20'
Don’t read this¶
Exploring #5835 (Link to detail of an enrolment fails for normal teachers)
This issue was fixed 20250107. Here is how to reproduce it:
Sign in as madeleine.carbonez on
prima1
.Click on “6A” in the “My groups” dashboard item.
In the “Projects” panel of 6A, click on the first pupil (Philémon Burton). Lino opens prima/EnrolmentsByGroup/61, which causes a BadRequest.
There is no error when you do the same as robin.
Explanation:
When madeleine (a simple teacher) calls obj2html()
on an enrolment, Lino
uses another actor than when robin calls it because a simple teacher cannot see
all enrolments. That’s normal. Robin has access to Enrolments, Madeleine only
to EnrolmentsByGroup. But Madeleine’s link then failed because EnrolmentsByGroup
requires a master instance (the group), which Lino didn’t specify. Until
20250107 Lino added mk and mt for specifying the master instance only when
the target link was on the same actor as the incoming request.
>>> renderer = settings.SITE.kernel.default_renderer
>>> grp = school.Group.objects.get(designation="6A", year__ref="2023/24")
>>> enr = school.Enrolment.objects.filter(group=grp).first()
>>> grp
Group #6 ('6A (2023/24)')
>>> enr
Enrolment #61 ('Philémon Burton (6A (2023/24))')
>>> ses = rt.login("robin", show_urls=True, renderer=settings.SITE.kernel.default_renderer)
>>> print(ses.permalink_uris)
None
>>> print(ses.obj2htmls(enr).replace(""", "'"))
<a href="javascript:window.App.runAction({ 'actorId': 'school.Enrolments', 'an': 'detail', 'rp': null, 'status': { 'record_id': 61 } })" style="text-decoration:none">Philémon Burton (6A (2023/24))</a>
>>> ses = rt.login("abel.adam", show_urls=True, renderer=settings.SITE.kernel.default_renderer)
>>> ar = projects.PupilsAndProjectsByGroup.create_request(master_instance=grp, renderer=renderer, user=ses.get_user())
>>> print(ar.obj2url(enr))
javascript:window.App.runAction({ "actorId":
"projects.PupilsAndProjectsByGroup", "an": "detail", "rp": null, "status": {
"base_params": { "mk": 6, "mt": 9 }, "record_id": 61 } })
Note: After fixing the bug, I changed PupilsAndProjectsByGroup to inherit from EnrolmentsByGroup rather than VirtualTable.