Customize delete behaviour¶
This section is a topic guide about how to customize behaviour around deleting records.
Unlike Django, Lino has PROTECT as the default on_delete strategy in ForeignKey
fields. If you want CASCADE, then you specify it explicitly using the
attribute on the model whose instances will be deleted.
disable_delete item in
data_record is a "preview" of whether
that row can be deleted or not. The front end may use this information to
disable or enable its delete button.
DeleteSelected action will
verify again before actually deleting a row.
When Lino analyzes the application's models at startup, it adds a
"disable_delete handler" (
lino.core.ddh) to every model.
When a user has view and write permission to an actor, they usually also have
permission to delete individual database rows using the
button in the toolbar. But before actually deleting a row, Lino will
disable_delete method do decide whether
the action will actually run. And you can override this method.
As an example, here is how the
lino_xl.lib.cal.GuestsByEvent table adds a customized veto
message to refuse deleting the presence of a guest in a calendar entry
for which Lino manages presences automatically:
@classmethod def disable_delete(cls, obj, ar): msg = super(GuestsByEvent, cls).disable_delete(obj, ar) if msg is not None: return msg mi = ar.master_instance assert mi == obj.event if mi.can_edit_guests_manually(): return None return _("Cannot edit guests manually.")
When you override this method, be careful to call
super() because Lino
finds a lot of veto reasons automatically for you by checking whether the
database contains related objects. For example. Lino by default forbids to
delete any object that is referenced by other objects. Users will get a message
of type "Cannot delete X because n Ys refer to it". See About cascaded
deletes below for customizing this behaviour.
About cascaded deletes¶
Lino changes Django's default behaviour regarding cascaded delete on ForeignKey
fields. You can set the
allow_cascaded_copy class attributes of a model to customize this
With Lino, unlike plain Django, you control cascaded delete behaviour on the
model whose instances are going to be deleted instead of defining it on the
models that refer to it.
So you usually don't need to care about Django's on_delete
attribute, Lino automatically (in
kernel_startup) sets this to
PROTECT for all FK
fields that are not listed in the
allow_cascaded_delete of their model.
- class lino.core.model.Model
A set of names of ForeignKey or GenericForeignKey fields of this model that allow for cascaded delete.
If this is a simple string, Lino expects it to be a space-separated list of field names and convert it into a set at startup.
This is also used by
lino.mixins.duplicable.Duplicateto decide whether slaves of a record being duplicated should be duplicated as well.
Example: Lino should not refuse to delete a Mail just because it has some
Recipient. When deleting a Mail, Lino should also delete its Recipients. That's