Welcome | Get started | Dive into Lino | Contribute | Topics | Reference | More

More chooser examples

This page is a tested document and the following instructions are used for initialization:

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

Choosers that need the requesting user

If your chooser method needs to know the current user to determine the choices for a field, include a "ar" parameter to your chooser method:

@dd.chooser()
def food_choices(cls, ar):
    year_in_school = ar.get_user().year_in_school if ar is not None else None
    food = []
    for name, reserved_for in MENU:
        if (year_in_school
                is None) or (reserved_for
                             is None) or year_in_school in reserved_for:
            food.append(name)
    return food

For example the chooser for the lino_xl.lib.tickets.Ticket.site field wants to know who is asking before deciding which choices to display, because not everybody can see every site.

>>> url = '/choices/tickets/Ticket/site'
>>> show_choices("robin", url) 
<br/>
pypi
security
>>> show_choices("luc", url) 
<br/>
docs
cust

Some special cases

Asking choices for a field that doesn't exist:

>>> show_choices("robin", '/choices/tickets/Ticket/foo') 
Traceback (most recent call last):
...
AttributeError: 'NoneType' object has no attribute 'blank'

Asking choices for a field that exists but has no choices:

>>> show_choices("robin", '/choices/tickets/Ticket/summary') 
Traceback (most recent call last):
...
Exception: Response status (/choices/tickets/Ticket/summary) was 404 instead of 200

When asking the choices for a field on a slave table, you must specify the master instance (even though it is not relevant):

>>> url = '/choices/tickets/TicketsByType/site?mk=1'
>>> show_choices("robin", url) 
<br/>
pypi
security

When lino.core.site.Site.strict_master_check is True, not specifying a master key when asking the choices for a field on a slave table is an error:

>>> settings.SITE.strict_master_check = True
>>> url = '/choices/tickets/TicketsByType/site'
>>> show_choices("robin", url) 
Traceback (most recent call last):
...
Exception: Response status (/choices/tickets/TicketsByType/site) was 400 instead of 200

lino.modlib.comments.CommentsByRFC is a slave table whose master field is a GFK. In that case you must also specify the master type; the master key is not enough.

>>> comments.CommentsByRFC.master_field  
<lino.modlib.gfks.fields.GenericForeignKey object at ...>
>>> comments.CommentsByRFC.master_field.name  
'owner'

A correct call:

>>> url = '/choices/comments/Comments/owner_id?mk=12&mt=37&owner_type=44&limit=3'
>>> show_choices("robin", url) 
<br/>
#1 (Föö fails to bar when baz)
#2 (Bar is not always baz)
#3 (Baz sucks)

A call without mt:

>>> show_choices("robin", '/choices/comments/CommentsByRFC/reply_to?mk=12&limit=3')
Traceback (most recent call last):
...
Exception: Response status (/choices/comments/CommentsByRFC/reply_to?mk=12&limit=3) was 400 instead of 200

The following snippet was used for reproducing #5440 (Changing the ticket of a comment doesn't work):

>>> comment = comments.Comment.objects.get(pk=258)
>>> comment.owner
Ticket #116 ('#116 (Why is foo so bar)')
>>> contenttypes.ContentType.objects.get_for_model(tickets.Ticket).pk
44
>>> comments.CommentsByRFC.master
<class 'django.contrib.contenttypes.models.ContentType'>
>>> url = '/choices/comments/CommentsByRFC/owner_id?mk=116&mt=44&owner_type=44&limit=3'
>>> show_choices("robin", url) 
<br/>
#1 (Föö fails to bar when baz)
#2 (Bar is not always baz)
#3 (Baz sucks)