Add iommi to a FBV¶
Let’s say we have a simple view to display an album:
def view_artist(request, artist_name):
artist = get_object_or_404(Artist, name=artist_name)
return render(
request,
'view_artist.html',
context={
'artist': artist,
},
)
There’s a table in the template for the tracks but it’s all manual written <table>, <tr>, etc tags and so doesn’t have sorting, and it’s just a lot of code in that template. It would be nicer to use an iommi table!
Add an iommi table¶
First the template is modified to extend "iommi/base.html" and wrap the content in {% block content %}.
Then we need to create the iommi object, and pass the collected assets to the context:
def view_artist(request, artist_name):
artist = get_object_or_404(Artist, name=artist_name)
albums = Table(
auto__rows=artist.albums.all(),
).bind(request=request)
return render(
request,
'view_artist2.html',
context={
'artist': artist,
'albums': albums,
'assets': albums.iommi_collected_assets(),
}
)
Now in the template we can add {{ albums }} to render the table, and we can delete all the old manually written table html.
AJAX dispatch¶
There are two problems with this code so far though, and that is that if we add filtering on album it breaks. One of the nice features of iommi is the automatic ajax endpoints (and by default a select2 widget), but this requires some extra routing, and that we include the relevant JS assets.
For views that are fully iommi the routing is done for you, but as this is a legacy function based view that we don’t want to rewrite fully right now, we’ll have to add the routing boilerplate ourselves:
def view_artist(request, artist_name):
artist = get_object_or_404(Artist, name=artist_name)
tracks = Table(
auto__rows=Track.objects.filter(album__artist=artist),
columns__album__filter__include=True,
).bind(request=request)
dispatch = tracks.perform_dispatch()
if dispatch is not None:
return dispatch
return render(
request,
'view_artist.html',
context={
'artist': artist,
'tracks': tracks,
'assets': tracks.iommi_collected_assets(),
}
)
Multiple iommi components¶
You should only create one top level iommi component in order to get the automatic namespacing for free. So if you wanted to add two tables, you should wrap them in a Page:
def view_artist(request, artist_name):
artist = get_object_or_404(Artist, name=artist_name)
class MyPage(Page):
albums = Table(auto__rows=artist.albums.all())
tracks = Table(
auto__rows=Track.objects.filter(album__artist=artist),
columns__album__filter__include=True,
)
page = MyPage().bind(request=request)
dispatch = page.perform_dispatch()
if dispatch is not None:
return dispatch
return render(
request,
'view_artist3.html',
context={
'artist': artist,
'tracks': page.parts.tracks,
'albums': page.parts.albums,
'assets': page.iommi_collected_assets(),
}
)
Using iommi’s base template with a FBV¶
For existing FBVs, you can get the iommi MainMenu and the base style
assets by simply extending iommi/base.html:
def view_artist(request, artist_name):
artist = get_object_or_404(Artist, name=artist_name)
return render(
request,
'view_artist4.html',
context={
'artist': artist,
}
)
{% extends "iommi/base.html" %}
{% block content %}
<h1>{{ artist }}</h1>
<ul>
{% for album in artist.albums.all %}
<li>
{{ album }}
</li>
{% endfor %}
</ul>
{% endblock %}