Thursday, April 30, 2020

I recorded a next screen cast about calendar management in Lino Presto, also about the municipality field.

https://youtu.be/NwpJH349D18

But I had some work before Lino was ready for this. Because I discovered that the filter parameters in calendar views were still being ignored. This caused a whole series of internal changes.

We have a new plugin parameter lino_xl.lib.calview.Plugin.params_layout, which specifies the layout of the table parameters used by all calendar views.

calview.EventsParameters must not call Event.setup_parameters but Events.setup_parameters.

This change in turn caused the problem that setup_parameters requires Actor.model to be resolved. Until now kernel called class_init() on each actor, and class_init() called setup_parameters(). But calview.EventsParameters for some reason is coming before cal.Events. To fix this, I splitted Actor.class_init into a new method init_layouts()

Now the other problem: all those methods that map parameter values to queryset filters. The param_values AttrDict contains only values for those parameters that are being used. Which is a problem.

There was no more need for a separate calendar_param_filter() method on cal.Event, so I removed it.

I also understood why I had to write:

if pv.get('project__municipality'):

instead of the usual:

if pv.project__municipality:

The latter syntax failed for tables on cal.Event that don’t have the field mentioned in their params_layout. Because, yes, remote fields are kind of volatile fields and get created on the fly when a layout asks for them. That’s why, when you want to use a remote field as table parameter, you should also write a setup_parameters method on your model:

from lino.core.fields import make_remote_field

@classmethod
def setup_parameters(cls, params):
    super(Event, cls).setup_parameters(params)
    params['project__municipality'] = make_remote_field(cls, 'project__municipality')

@classmethod
def get_request_queryset(cls, ar, **filter):
    qs = super(Event, cls).get_request_queryset(ar, **filter)
    pv = ar.param_values
    if pv.project__municipality:
        places = pv.project__municipality.whole_clan()
        qs = qs.filter(project__isnull=False, project__city__in=places)
    return qs

Before committing, I had once more some fun with writing documentation about these things. I am still far from having finished. I added the --keep-going option to inv bd.