Welcome | Get started | Dive | Contribute | Topics | Reference | Changes | More
More about slave tables¶
We have been introduced to slave tables, but there is more to say about them.
Slave tables with special masters¶
The master of a slave table can be something else than a database row. For example
in
lino_xl.lib.accounting.MovementsByMatch
the master is astr
in
lino_xl.lib.calview.DailyPlanner
the master is alino_xl.lib.calview.Day
instancein
lino_welfare.modlib.debts.PrintEntriesByBudget
the master is anEntryGroup
If the master instance is not a subclass of lino.core.fields.TableRow
,
it must be JSON serializable.
Slave tables with remote master¶
The master_key
of a slave table can be a remote
field.
When you have three models A, B and C with A.b being a pointer to B and B.c being a pointer to C, then you can design a table CsByA which shows the C instances of a given A instance by saying:
class CsByA(Cs):
master_key = "c__b"
For example lino_xl.lib.courses.ActivitiesByTopic
shows all activities
about a given topic. But an activity has no foreign key topic
, so
you cannot say master_key = 'topic'
. But a course does know its topic
indirectly because it knows its activity line, and the activity line
knows its topic. So you can specify a remote field:
class ActivitiesByTopic(Courses):
master_key = 'line__topic'
allow_create = False
A slave table with a remote master should have allow_create
set to False because we cannot set a
line for a new course.
Other examples
Multiple master fields¶
In Lino Prima, a cast is when a given teacher gives a given subject to a given group of pupils. And similarly, an exam is usually (but not always) done by a given teacher about a given subject in a given group.
But there is no direct pointer from exam to cast because not every exam requires
a cast. When we open the detail view of a cast, we want to see a list of all
exams for this cast. Here is how to declare the
lino_prima.lib.ratings.ExamsByCast
table:
class ExamsByCast(Exams):
required_roles = dd.login_required(PrimaTeacher)
master = "prima.Cast"
column_names = "seqno designation period *"
@classmethod
def get_request_queryset(self, ar, **filter):
mi = ar.master_instance
assert isinstance(mi, rt.models.prima.Cast)
qs = super().get_request_queryset(ar, **filter)
# When there are two teachers for a same subject, they can optionally
# manage exams together.
if manage_exams_separately:
qs = qs.filter(subject=mi.subject, group=mi.group, user=mi.user)
else:
qs = qs.filter(subject=mi.subject, group=mi.group)
return qs