General

How do I find the path to a parameter?

Navigating the namespaces can sometimes feel a bit daunting. To help with this iommi has a special debug mode that can help a lot. By default it’s set to settings.DEBUG, but to set it explicitly put this in your settings:

IOMMI_DEBUG = True

Now iommi will output data-iommi-path attributes in the HTML that will help you find the path to stuff to configure. E.g. in the kitchen sink table example a cell looks like this:

<td data-iommi-path="columns__e__cell">explicit value</td>

To customize this cell you can pass for example columns__e__cell__format=lambda value, **_: value.upper().

Instead of looking at the DOM, you can use the “pick” tool where you can get the path by clicking on the item you want. You will also get a link to the right place into the API docs for the thing you clicked on.

Another nice way to find what is available is to append ?/debug_tree in the url of your view. You will get a table of available paths with the ajax endpoint path, and their types with links to the appropriate documentation.

If IOMMI_DEBUG is on you will also get the iommi debug toolbar on your pages. Code will jump to the code for the current view in PyCharm. You can configure the URL builder to make it open your favored editor by setting IOMMI_DEBUG_URL_BUILDER in settings:

IOMMI_DEBUG_URL_BUILDER = lambda filename, lineno: f'my_editor://{filename}:{lineno}'

Visual Studio Code example:

IOMMI_DEBUG_URL_BUILDER = lambda filename, lineno: f"vscode://file/{filename}:{lineno}:0"

The Tree link will open the ?/debug_tree page mentioned above.

How do I access a sibling component?

Let’s say we have a Page with a form and a custom template, and we want to access the form, we can do that via the root object:

class MyPage(Page):
    edit_album = Form.edit(auto__model=Album, instance=album)
    view_album = Template('''
        {{ root.parts.edit_album.fields.name.value }}
    ''')
▼ Hide result
Toggle structure

How do I use a custom class for the columns/fields/filters of a component?

A Table creates Column instances, a Form creates Field instances and a Query creates Filter instances. If you have a custom subclass that you want iommi to use instead when it auto-generates members from a model, set member_class:

class MyColumn(Column):
    pass

class MyTable(Table):
    class Meta:
        member_class = MyColumn

table = MyTable(auto__model=Album)
▼ Hide result
Toggle structure

A Table also has a nested Form (used for bulk editing and create) and a nested Query (used for filtering). Swap those out with form_class and query_class, and the Form that a Query builds for its filters with form_class:

class MyField(Field):
    pass

class MyForm(Form):
    class Meta:
        member_class = MyField

class MyFilter(Filter):
    pass

class MyQuery(Query):
    class Meta:
        member_class = MyFilter
        form_class = MyForm

class MyTable2(Table):
    class Meta:
        member_class = MyColumn
        form_class = MyForm
        query_class = MyQuery

The same pattern applies to the other parts a component builds. A Form uses action_class for its actions and page_class for when it is rendered as a standalone page:

class MyAction(Action):
    pass

class MyForm2(Form):
    class Meta:
        action_class = MyAction