Skip to content

Commit

Permalink
Doc update
Browse files Browse the repository at this point in the history
  • Loading branch information
boxed committed Oct 4, 2024
1 parent bd2792a commit cbaf59c
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 4 deletions.
2 changes: 1 addition & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ Contents:

getting_started
tutorial
production_use
equivalency
cookbook
forms
Expand All @@ -30,6 +29,7 @@ Contents:
admin
styles
registrations
production_use
api
philosophy
architecture
Expand Down
95 changes: 92 additions & 3 deletions docs/test_doc_equivalency.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,104 @@ def test_equivalence():
Equivalence
===========
In iommi there are multiple ways to accomplish the same thing. The two most obvious ways are declarative and programmatic. But there are different paths even within those two main paths. This page is an overview of a few of those ways. Hopefully you will see the philosophy through these examples. Let's get started!
In iommi there are two equivalence principles that are important to grasp:
- declarative/programmatic hybrid API
- double underscore as a short hand syntax for nesting dicts
First a model:
The model used for these examples is `Album`:
.. literalinclude:: models.py
:start-at: class Album
:end-before: def __str__
:language: python
Declarative/programmatic hybrid API
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The programmatic API is pretty straight forward: you have a class constructor that takes some arguments. The interesting part is how we can mirror that *exactly* into a declarative style.
"""

table = Table(
model=Album,
columns=dict(
name=Column(),
),
)

# language=rst
"""
This simple table can be written as a class definition:
"""

class MyTable(Table):
class Meta:
model = Album

name = Column()

# language=rst
"""
There are two things to notice here:
1. Variables declared in `class Meta` in iommi means they get passed into the constructor. `model = Album` in `Meta` is exactly the same as `Table(model=Album)`.
2. The `name` column is declared on the class itself, and the `columns` part of the argument (`Table(columns=dict(...)`) is implicit. For `Page` the same implicit name is called `parts`, and for `Form` it's called `fields`.
Double underscore short form
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In iommi you can have very deeply nested object structures, and because you want to customize something deep inside a graph it would be cumbersome to nest dicts a lot. So `__` is used a separator.
Say we have a table, where we want to turn on filtering for a column, but we want to insert a special CSS class (called `special`) on the label of the search field:
"""

table = Table(
auto__model=Model,
# Enable filtering
columns__name__filter__include=True,
# Set the CSS class on the label
columns__name__filter__field__label__attrs__class__special=True,
)

# language=rst
"""
We could also write this without using `__` for nesting:
"""

table = Table(
auto=dict(model=Model),
columns=dict(
name=dict(
filter=dict(
# Enable filtering
include=True,
# Set the CSS class on the label
field=dict(
label=dict(
attrs={
# have to use a dict literal here,
# because `class` is a reserved keyword in Python
'class': dict(
special=True,
),
},
),
),
),
),
),
)

# language=rst
"""
These two things have exactly the same meaning, but the `__` syntax is a lot shorter and cleaner.
"""

# language=rst
"""
Further examples
~~~~~~~~~~~~~~~~
"""

# language=rst
Expand Down

0 comments on commit cbaf59c

Please sign in to comment.