Welcome | Get started | Dive | Contribute | Topics | Reference | Changes | More


This is the 2021 change log for Developer Guide. General information about how to read and maintain this document in Documenting changes.


New virtual field DelayedHtmlBox to the fields collection.


New feature: a HtmlBox can now be collapsible. See Specifying widget options in a layout.


New plugin lino.modlib.search. First use case will be Lino Noi.


Add Site attribute Site.use_elasticsearch which when set to True makes the class lino.core.model.Model inherit from necessary mixins related to ElasticSearch.


Add lino.modlib.elastic plugin (draft) for more intelligent search capabilities.

Release to PyPI: lino, lino_react, lino_noi, lino_xl


Bugfix third-party auth buttons didn’t work in ExtJS. Lino Noi no longer uses lino_xl.lib.votes (we will soon add a new plugin nicknames instead). New field type lino.core.fields.PreviewTextField.

Release to PyPI: lino xl, react and noi


WIP in lino_xl.lib.votes: get_vote_raters() and use_candidatures.

notify.remove_after now in days (no longer in hours)


Optimize blogs, display_mode ‘story’, react cosmetics, use votes in noi tickets, add third party authentication actions in SignIn and CreateAccount window. Fix a breaking bug in Lino Noi (cannot create ticket).

Release to PyPI: xl lino react


Remove Actor attribute borderless_list_mode and implement StoryElement as a substitute, with usage trigger display_mode as ‘story’.


Add the lino_xl.lib.votes plugin to Lino Noi. Optimize how Lino Noi looks for anonymous users. Fix a bug that caused Lino Noi to not send notifications to all team members.


Cosmetic optimization: The button_text of the LedgerRegistrable.toggle_state and UploadController.show_uploads actions used unicode symbols that weren’t being rendered correctly in some browsers.

Release to pypi: lino, xl, cosi, amici, react


After upgrading you might need to review your settings.py file: The max_file_size and upload_to_tpl settings are now an attribute of lino.core.site.Site and no longer a plugin attribute in lino.modlib.uploads.

The lino_xl.lib.bevat plugin had some bugs in the VAT rules, and it now can export a intra-community statement to XML.


In lino_xl.lib.cal, added a three new fields to Event model: Event.notify_before, Event.notify_unit and Event.notified. Added a scheduler function event_notification_scheduler() to send out notifications for the scheduled events.


The model VatSubjectable has a new property vid_manager which is essentially a VatNumberManager instance that facilitates VAT identification number validation, both online and local, and generation of fake VAT identification number for demo purposes.

A new data Checker VatIdChecker on VatSubjectable is active when the plugin vat is installed and reports non-existent VAT identification number by doing online registry checks to the corresponding user.

These additions are available/published on (and above) lino_xl-21.8.2.


Release to PyPI : xl, noi and react


Release to PyPI : lino, xl, cosi and react

Bugfix: Lino failed to print the customer’s VAT id in sales invoice when using the default weasyprint template.


Minor optimization for registering purchase invoices with partly deducible VAT: when you manually change the vat_class of an invoice item, then Lino now re-computes all amounts of that item, based on the invoices total amount and the new VAT class.


Inject field default_color into SiteConfig model from cal plugin.


Add a plugin attribute lino.modlib.help.Plugin.make_help_pages.


Release to pypi: lino-cosi lino-react


Release to pypi: lino-xl


Release to pypi: lino, lino-react


The lino_xl.lib.invoicing plugin now supports “periodic” invoice generators, a new feature used in Lino Noi for automatically generating yearly or monthly invoices for membership fees. Implemented by lino_xl.lib.orders.


Renamed to WrappedAction from QuickLinkAction.

Extended Action attribute js_handler to have the possibility to have it defined as a class method.


Renamed Renderer.hide_dashboard_items to Renderer.support_dashboard_layout.

Release to PyPI: lino, react


Extended collectstatic to run makehelp as a sub task.

Added, Kernel.lino_version, functionally similar to Kernel.code_mtime to use as production site modification stamps.

Release to PyPI: lino


Added Site.build_site_cache_url() and Site.site_cache_root to Site object.

Also, extended the django.contrib.staticfiles command collectstatic to build the site cache before executing collect() on static dirs.

Release to PyPI: lino


Renamed plugin option use_verify to allow_online_registration.

Release to PyPI: lino


Release to PyPI: getlino, lino, xl, react, cosi, amici, noi


  • Optimizations in the React front end

  • extracted help texts are now implemented by separate plugin lino.modlib.help.

  • users.User didn’t have a merge action


Release to PyPI: lino, xl, react, cosi, amici, noi, getlino


Release to PyPI: lino, xl, react, cosi, amici


The lino.modlib.system.SiteConfig.pupil_guestrole field is now injected by the lino_xl.lib.courses and no longer by Lino Voga.

The SiteConfig detail layout in Lino Amici now shows the fields injected by cal and courses.

The Help button (?) now also works in ExtJS, and it now links to the appropriate page of the docs.


The email notification caused by AjaxExceptionResponse on a production site no longer includes the whole traceback in the message’s subject.


#4195 (Lost connection to MySQL server during query) #4194 (insert window doesn’t close after submitting)

Release to PyPI: lino 21.6.1, lino_react 21.6.1. and lino_noi 21.6.1.


Release to PyPI : lino 21.6.0, xl 21.6.0, noi 21.6.0 and react 21.6.0.


Release Lino 21.5.0 to PyPI.


Internal optimizations: lino.core.store.StoreField.value2dict() now takes the field name as an argument. New utility function lino.api.doctest.walk_store_fields(). get_complexity_factors now uses lino.core.actors.Actor.is_abstract()


New plugin option lino.modlib.notify.mark_seen_when_sent When this is True, Lino marks notification messages as seen as soon as they have been sent via email.

The default implementation of lino.core.actors.Actor.get_table_summary() now uses lino.core.requests.BaseRequest.plain_toolbar_buttons().


Added a new field User.date_format for all applications. New plugin option use_verify. User.send_welcome_email is no longer a window action.

Release to PyPI: Lino 21.4.2, xl 21.4.2, Noi 21.4.1, Voga 21.4.0, Così 21.4.1

Release to PyPI: React 21.5.0

Added a new function lino.core.auth.utils.activate_social_auth_testing(), which does what was priviously done only in lino_book.projects.noi1e and which is now used also for lino_shop.projects.shop1.


New actor attribute lino.core.actors.Actor.params_panel_pos.


New actor attribute lino.core.actors.Actor.params_panel_pos.


Release to PyPI : Lino 21.4.1, XL 21.4.1, Lino Noi 21.4.0 and React 21.4.0.


New mixin lino.modlib.memo.BabelPreviewable. First use case is lino_xl.lib.products, where Product and Category now inherit from it. Their database structure is changed: renamed field description to body. The read-only fields short_preview and full_preview of lino.modlib.memo.Previewable are now named body_short_preview and body_full_preview.

Release to pypi: lino 21.4.0, lino-xl 21.4.0


The lino_xl.lib.products plugin now adds card and list layouts for product, and it adds quick links.


lino_xl.lib.cal.MyTasks is now sorted in ascending chronological order.

A lino_xl.lib.notes.SpecialType now has methods get_object() and set_object().


Calling lino.sphinxcontrib.configure() in a Sphinx conf.py file now uses the insipid theme instead of the pydata_sphinx_theme.


Adapted Lino to changes in Django 3.2: Until now the value of a QuantityField was a Decimal, not a Quantity. The Quantity class refused to get instantiated, it was just the base class for Duration and Percentage. But now the value of a QuantityField is no longer a Decimal but a Quantity. The only difference between a Quantity and a Decimal is that a Quantity has a len() in order to satisfy Django when calling Field.clean().


Started #4085 (A common Sphinx layout for non-tech docs like cg, hg and sr).


The users.MySettings quicklink now comes automatically with the users plugin (#4075)

The lino.core.actors.Actor.get_default_action method is now being called when all other standard actions have been bound. Removed the lino_xl.lib.accounting.Situation table, which was no longer used. The lino.core.plugin.Plugin.get_quicklinks() method can now yield a dict.


New action lino_xl.lib.contacts.Partner.import_text. This is not yet fool-proof. An experiment for #4061 and #3895.

New actor attribute Actor.allow_delete. We need it e.g. for lino.modlib.system.SiteConfig, which, indeed is not Actor.readonly (because every site manager can edit the site parameters), but even for a site manager it makes no sense to delete this record.


lino_xl.lib.phones.ContactDetail now inherits from lino.mixins.periods.DateRange, i.e.:

  • added a field lino_xl.lib.phones.ContactDetail.start_date.

  • we can now filter the contact details that are active in a given date range.


New database model lino_xl.lib.accounting.PaymentMethod. New plugin lino_xl.lib.shopping.


lino_xl.lib.tickets.Ticket.priority is now an IntegerField. To migrate existing priorities correctly, simply edit the restore.py of your pm dump2py snapshot and change one line in the create_tickets_ticket() function: kw.update(priority=priority) –> kw.update(priority=50-int(priority))


Release to PyPI : welfare, weleup and welcht 21.3.0. Followed by bugfix releases lino, welfare, weleup and welcht 21.3.1


#4007: babelkw now includes str2kw. This avoids us to get locked by code that still uses babelkw(). Translators can now add translations for new languages without having to edit the German, French and Estonian .po files. Usage: in any existing source code for which you want to provide new translations, replace babelkw("name", en="foo", de=...) by babelkw("name", _("foo"), de=...).


Added zh-hant (traditional Chinese) to the list of supported translations for lino, lino_xl and lino_cosi. Added a demo project lino_book.projects.cosi4, which uses zh-hant. Increased the max_length of lino.utils.mldbc.fields.LanguageField from 5 to 7 in order to support languages like zh-hant. Reviewed the How to contribute translations page.

Released to PyPI: atelier 1.1.28, lino 21.3.0, lino_xl 21.3.0 and lino_cosi 21.3.0.



Fixed #3993 (session has no ticket).

Added a first series of primeicon icons as Sphinx substitution definitions. No we can insert the buttons filter button, plus-circle button, refresh button, trash button and user button into doc pages. The doctree must use the lino.sphinxcontrib.logo extension, and the page must include a file similar to our /shared/include/defs.rst file.


Miscellaneous bugfixes and changes regarding users of type contributor in Lino Noi.

Release to PyPI : lino 21.2.5, XL 21.2.3, Noi 21.2.0.


Fixed #3986. New methods get_request_detail_action and lino.core.layouts.Layout.add_datasource() to fix a subtle problem in Lino Avanti. Also Layout._other_datasources is no longer a set but a list. The case is covered in Who can see the detail of an activity?.

Release to PyPI: Lino 21.2.4 and XL 21.2.2

Fixed #3987 (checkdata says ‘SiteConfig’ object has no attribute ‘pupil_guestrole’). The error occurred only when the guest_role of an activity line was empty, that’s why it slipped through the test suite.


Released Lino 21.2.3 and XL 21.2.1 to PyPI (to fix issues like this one).


Optimizations in lino.modlib.uploads: Added new plugin options remove_orphaned_files and max_file_size, and two data checkers UploadChecker and UploadsFolderChecker.


API change: Rename lino.mixins.Uploadable to lino.modlib.uploads.mixins.UploadBase.

Fixed a typo bug in renderer_mixin.JsCacheRenderer which caused Lino to create an empty media directory “upload” (instead of “uploads”) at startup. This bug might be the cause for missing group write permission of files that were uploaded to a production site. If you encounter this problem, check whether your uploads directory has the sticky group bit set.


Optimizations for developers: New django-admin command demotest increases test coverage. Removed WebIndexTestCase, which is functionally included in demotest. Miscellaneous cleanup and optimizations in the test suite. Removed Django 4 deprecation warnings.

Regression danger: lino_react.react.views.ApiElement.post() no longer passes http.QueryDict(request.body) but request.POST as data to action_request.

Release to Pypi: lino-21.2.2


Fixed #3968 (extjs combobox doesn’t submit empty value). It is possible that this bugfix reopens #3653 (Learning choosers don’t work in React front end).


Release to PyPI: Lino, XL and Avanti.

Minor bugfixes : SignIn failed when lino.core.site.Site.use_ip_dict was not True. When lino.modli.memo.PreviewableChecker was called with –fix, it fixed the problems but didn’t report how many problems were fixed.

Fixed a regression: Insert button was missing in lino.modlib.comments.CommentsByRFC. All comment table summaries are now wrapped into html_text, leading to better text styling under lino.modlib.extjs.

New feature: you can now set a new plugin setting lino.modlib.comments.Plugin.emotion_range to either “business” (default) or “social” to select between two alternative sets of emoticons. Lino Avanti uses the new “social” range, Lino Noi the default “business” range.

Extend WebIndexTestCase to use DemoTestCase.login() instead of Django’s client force_login(). So now the JavaScript files are being built for each user type, and a typo bug like AttrDict instance has no key 'ipdict' (in Lino 21.2.0) would no longer go undetected.

Release to PyPI: Lino and Avanti.


Fixed a bug in lino.modlib.ipdict that caused it to not report when an IP had been blacklisted.


Fixed #3948: Lino didn’t behave correctly when (a) no weekday at all was selected (which for Lino means “any weekday”), and (b) caused an internal server error when no recursion rule was found. This was in the get_next_suggested_date() of a lino.modlib.system.RecurrenceSet.

Fixed #3946: When a partner is lino_xl.lib.lists.Member of some list, this is no longer a reason to refuse deleting the partner. When you confirm to delete such a partner, the list memberships now get deleted as well (in cascade).

The title of the lino_xl.lib.contacts.RolesByPerson slave panel was “Contact for of (name)”, not very helpful. Now it is “(name) is contact person for”. Added a custom details_of_master_template. Note that the custom label, “Contact for” is also needed for situations where the master is not known.


The ipdict.Connections table has been reimplemented as lino.modlib.users.Sessions. It now uses sessions and therefore works also on sites with very many users. It also features a “Kill” action to manually delete individual actions. ipdict is no longer used to show the list of active user sessions. The ipdict approach was not suitable for sites with very many users because it stores every connection in an in-memory dict. ipdict is used only for detecting brute force attacks. It now removes every entry after a successful authentication.

Internal changes: lino.core.auth.middleware.DeviceTypeMiddleware has been merged into lino.core.auth.middleware.WithUserMiddleware because it was inefficient to parse the request twice. BoundAction has now a __str__() method, which is used by user warnings “No permission to run X”. Until now these warnings were irritating because the action name wasn’t shown in the browser.


New method lino.modlib.ipdict.Plugin.pop_ip_record() removes an (ip address, username) pair from the registry, and Lino uses this when receiving the user_logged_out signal.


Continued on #1162 (A CMS using Lino). The lino_book.projects.cms project now has some improvement. But it is not finished. Internal changes: lino.core.dashboard.DashboardItem.render() now yields html chunks instead of etree elements. show_dashboard() and show_menu() are now defined in lino.api.doctest, no longer as methods of a request. The function lino.api.doctest.rst2menu() is now used in More about the main page.

The menu of a multilingual site now shows the languages in the main menu, and users can dynamically switch to another language than the on defined in their preferences.


Fix #3921 (Journal entry mixes up debit and credit when creating the movements). Fix #3924 (auto_compute_amount does not always work as expected).

Release to PyPI: XL 21.1.6.


Release to PyPI: Lino 21.1.1.

Optimizations: #3919 (No suggestions on clearable general account) FinancialVoucherItem.account_changed() didn’t collect suggestions after entering a clearable account. #3920 (Lino registers the voucher even when exception happens).

Release to PyPI: Lino 21.1.2 and XL 21.1.5.


Release to PyPI: Lino Extensions Library 21.1.3.

Fix some bugs in lino_xl.lib.finan : The choicelist for FinancialVoucherItem.match didn’t respect the suggest_future_vouchers settings and therefore always showed all matches, including those that happen in the future and won’t get satisfied. Visible result: you select one of these matches, but Lino then sets the field to blank. After selecting a partner, Lino didn’t suggest anything (because amount was 0.00, not None). FillSuggestionsToVoucherItem caused an additional item to be created.

Release to PyPI: Lino Extensions Library 21.1.4 and Lino 21.1.0

Fix #3917 (Lino forgets the journal after saving a bank statement).


Miscellaneous minor optimizations for entering bank statements. finan.DatedFinancialVoucherItem now also fills the date field from last_item_date. Trying to fix surprizing behaviour after FillSuggestionsToVoucherItem. Ledger movements in accounting.MovementsByVoucher are now ordered by seqno, i.e. by their “natural” order of creation.

Fix a typo bug in lino_xl.lib.cal that caused Lino to no show anything in cal.EntriesByGuest although the person was present in some calendar entry.


Add new item vatless to lino_xl.lib.vat.VatClasses.

Fix #3909. After editing the entry_date of the last voucher of the journal we don’t want its number to increase.


Fix #3906 (active_fields are disturbing for city and zip_code). In lino_xl.lib.countries.CountryCity the fields city and zip_code are no longer active_fields.

Fix #3905 (Purchase invoice from private person suggests VAT). This was a bug in lino_xl.lib.eevat and lino_xl.lib.bevat.

Fix #3907 (Cannot enter into “Expense” column of bank statement)

Release to PyPI: Lino Extensions Library (2 versions)


Optimized column layout of lino_xl.lib.trading.InvoicesByJournal.

Release to PyPI: Lino Extensions Library.