Plugin reference for developers humanlinks : managing family relationships
previous households
next invoicing : Generating invoices

humanlinks : managing family relationships¶

The lino_xl.lib.humanlinks module adds functionality for managing Links between humans.

It is often used in combination with lino_xl.lib.households.

  • Links between humans

  • Lars

  • Reproduce #4185

This is a tested document. The following instructions are used for initialization:

>>> import lino
>>> lino.startup('lino_book.projects.min9.settings')
>>> from lino.api.doctest import *

Links between humans¶

The links between humans are directed: they have a Link.parent and a Link.child (i.e. they go from one person to another person).

Human links also have a type.

Assume that we have two persons F and S, and a human link of type "parent" between them, which says that F is the father of S. The link will be of type LinkTypes.parent and go from F to S.

In the detail window of S, we want that link to say "father" (because S says that F is my father). But in the detail window of F, we want that link to say "son" (because F says that S is my son).

>>> rt.show(humanlinks.LinkTypes)
======= ================= ================== ==================== ================= ===================
 value   name              male parent text   female parent text   male child text   female child text
------- ----------------- ------------------ -------------------- ----------------- -------------------
 01      parent            Father             Mother               Son               Daughter
 02      adoptive_parent   Adoptive father    Adoptive mother      Adopted son       Adopted daughter
 03      grandparent       Grandfather        Grandmother          Grandson          Granddaughter
 05      spouse            Husband            Wife                 Husband           Wife
 06      friend            Friend             Friend               Friend            Friend
 07      partner           Partner            Partner              Partner           Partner
 08      stepparent        Stepfather         Stepmother           Stepson           Stepdaughter
 09      foster_parent     Foster father      Foster mother        Foster son        Foster daughter
 10      sibling           Brother            Sister               Brother           Sister
 11      cousin            Cousin             Cousin               Cousin            Cousin
 12      uncle             Uncle              Aunt                 Nephew            Niece
 80      relative          Relative           Relative             Relative          Relative
 90      other             Other              Other                Other             Other
======= ================= ================== ==================== ================= ===================
class lino_xl.lib.humanlinks.Link¶

A link between two persons.

parent¶

Pointer to the person who is "parent".

child¶

Pointer to the person who is "child".

type¶

The type of link. Pointer to LinkTypes.

type_as_parent¶

Displays LinkTypes.as_parent() for this link.

type_as_child¶

Displays LinkTypes.as_child() for this link.

check_autocreate(self, parent, child)¶

Check whether there is a human link of type "parent" between the given persons. Create one if not. If the child has already another parent of same sex, then it becomes a foster child, otherwise a natural child.

Note that the ages are ignored here, Lino will shamelessly create a link even when the child is older than the parent.

This is called from full_clean() of lino_xl.lib.households.Member to automatically create human links between two household members.

class lino_xl.lib.humanlinks.LinkTypes¶

The global list of human link types. This is used as choicelist for the Link.type field of a human link.

The default list contains the following choices:

adoptive_parent¶

A person who adopts a child of other parents as his or her own child.

stepparent¶

Someone that your mother or father marries after the marriage to or relationship with your other parent has ended

foster_parent¶

A man (woman) who looks after or brings up a child or children as a father (mother), in place of the natural or adoptive father (mother). [thefreedictionary]

class lino_xl.lib.humanlinks.LinkType¶
symmetric¶

Whether this link is symmetric (i.e. text is the same for both directions). For example sibling, friend, spouse are symmetric links.

class lino_xl.lib.humanlinks.LinksByHuman¶

Show all links for which this human is either parent or child.

Display all human links of the master, using both the parent and the child directions.

This is a usage example for having a get_request_queryset method instead of master_key.

It is also a cool usage example for the get_table_summary method.

Lars¶

Lars Braun is the natural son of Bruno Braun and Eveline Evrard. Here is what Lars would say about them:

>>> Person = rt.models.contacts.Person
>>> Link = rt.models.humanlinks.Link
>>> lars = Person.objects.get(first_name="Lars", last_name="Braun")
>>> for lnk in Link.objects.filter(child=lars):
...    print(u"{} is my {}".format(lnk.parent,
...         lnk.type.as_parent(lnk.parent)))
Mr Bruno Braun is my Father
Mrs Eveline Evrard is my Mother
Mr Albert Adam is my Foster father
Mrs Françoise Freisen is my Foster mother
Mrs Daniela Radermacher is my Foster mother

Both parents married another partner. These new households automatically did not create automatic foster parent links between Lars and the new partners of his natural parents.

Reproduce #4185¶

The following snippet covers #4185 (Human link, "Create relationship as ... Brother but Lino sets it to Father"). It uses BeautifulSoup. Read the docs in case you don't yet know this tool.

>>> LinksByHuman = humanlinks.LinksByHuman
>>> ses = rt.login("robin", renderer=settings.SITE.kernel.default_ui.renderer)
>>> html = tostring(humanlinks.LinksByHuman.get_table_summary(lars, ses))
>>> soup = BeautifulSoup(html)
>>> print(soup.get_text(" ", strip=True))  
Lars is Foster son of Daniela RADERMACHER (unknown) Foster son of Albert ADAM
(41 years) Son of Bruno (41 years) Son of Eveline EVRARD (40 years) Foster son
of Françoise FREISEN (40 years)
Create relationship as Father / Son Adoptive father / Adopted son Foster father
/ Foster son Husband Partner Stepfather / Stepson Brother Cousin Uncle / Nephew
Relative Other
>>> links = soup.body.find_all('a')
>>> len(links)
21

The first link after "Create relationship as" is "Father". This link works as expected, it pops up a window in which the field Link.type is set to "Father".

>>> print(links[5].get_text().strip())
Father
>>> print(links[5])  
<a href='javascript:Lino.humanlinks.LinksByHuman.insert.run(...
"type": "Father (Mother)"...">Father</a>

Our problem is that when clicking on any of the following links, the pop-up window still has its field Link.type set to "Father" instead of the link type on which I clicked.

For example let's click on the "Adopted son" link.

>>> print(links[8].get_text().strip())
Adopted son
>>> print(links[8])  
<a href='javascript:Lino.humanlinks.LinksByHuman.insert.run(...
"type": "Adoptive father (Adoptive mother)"...">Adopted son</a>

Here is the code (in the get_table_summary method of LinksByHuman) that creates these links:

# Buttons for creating relationships:
if self.insert_action is not None:
    sar = self.insert_action.request_from(ar)
    if sar.get_permission():
        actions = []
        for lt in self.addable_link_types:
            sar.known_values.update(type=lt, parent=obj)
            sar.known_values.pop('child', None)
            btn = sar.ar2button(None, lt.as_parent(obj), icon_name=None)
            actions.append(btn)
            if not lt.symmetric:
                actions.append('/')
                sar.known_values.update(type=lt, child=obj)
                sar.known_values.pop('parent', None)
                btn = sar.ar2button(None, lt.as_child(obj), icon_name=None)
                actions.append(btn)
            actions.append(' ')

        if len(actions) > 0:
            elems += [E.br(), gettext("Create relationship as ")] + actions

Note that we use a same action request instance (sar) to create all those links after the text "Create relationship as".

Note how ar2button works. It creates a temporary instance of Link that will never be saved, its "only" use is to get filled with values, which are used to generate the status information, which is needed to generate the values of the javascript href that puts the values of the fields into the popup window. This status information is cached, for performance reasons. But when we change known_values, Lino does not detect automatically that it should update the cached status information.

The problem was that we didn't call clear_cached_status between subsequent calls to ar2button.

Logo

Table of Contents

  • Welcome
  • About Lino
  • Developer Guide
  • Contributor Guide
  • Reference
    • Topics
    • Plugin reference for developers
    • Demo projects
    • Application specs
    • Repositories
    • Miscellaneous reference pages
  • API
  • Changes
  • News

Quick search

  • General Index
  • Python Module Index

© Copyright 2002-2022 Rumma & Ko Ltd. Last updated on 2022-08-09. Created using Sphinx 5.1.1. Insipid Theme. Source code.
Online link: https://dev.lino-framework.org/specs/humanlinks.html.