Hypermedia driven maps
Published October 13, 2024
This video features Anders HovmoĢller at Django Day Copenhagen 2020 in Copenhagen, Denmark.
iommi is a high level framework to radically accelerate building django apps. Write reusable pages and CRUD views way faster without templates and still customize every bit and end up with almost no code.
Django Day Copenhagen 2020
Anders Hovmƶller introduces iommi, a Django library that grew from HTML tables into query-set filtering, forms, composable pages, and an admin interface. Its declarative, double-underscore configuration lets developers generate tables and forms from models while progressively customizing cells, templates, layouts, permissions, filters, actions, styling, and URLs without rebuilding components. He shows automatic sorting, pagination, filtering, foreign-key lookups, CRUD views, bulk actions, and query optimization, while arguing that related view concerns should live together in one coherent definition rather than being scattered across hooks and templates.
Summarised automatically from the transcript.
Automatically transcribed, so expect mistakes in names and technical terms.
Speaker 1: Hi. My name is Anders and I'm going to talk about Iomi uh named after the guitarist. It's a library me and my colleague Johan Libke have been working towards since 2014. So it started with a library to do HTML tables, then it expanded to a library for filtering query sets. Then we added a form library to deal with things Django forms couldn't handle well for us. And then finally a way to assemble and compose these into complex pages. This is going to be a fast and quite shallow introduction to Iomi because I have a lot of things to cover But I hope it shows the power of the library and
Speaker 1: why we made it. So the structure of this talk is going to be sort of like a fake live coding session where I jump forward to pre-prepared commits and maybe actually do some live coding if if need be. So I'm gonna build a little app, which is a discography app. We're gonna have artists and albums and tracks. So we'll just start directly looking at the the Django models. So we have an artist with a name And an album with a name and artist in a year. The year is just the release date of the album And we have it we have tracks belonging to albums with the name at the index which is the order in the album, which album they uh
Speaker 1: sort of are in and the duration I'm I'm cheating here just in character field because it looks a little bit better and simpler in the demo. Yeah. So we'll start off with the most simplest Django you can think of. I have the models and my URLs are there's an index page. It just renders an index. html with uh two things in it, the content and the title. The index page is Exactly what you'd expect and the base. html is just uh it's basically setting up bootstrap. So we're gonna end up uh here So that's like the the foundation to stand on, right?
Speaker 1: So this is simple and nothing special. And now we're gonna go forward and First we're gonna install Iomi, it's simple as pip install iomi. And then in settings we're gonna add in installed apps, I owe me, and there's a middleware too. I'll uh go into them why we want that later. That's the uh that's the installation Uh yeah, I forgot to stop my start my stopwatch. Ha There we go. So we start with a declarative table because HTML tables are an important part of Iomia and
Speaker 1: one of the most powerful features. So we're gonna do uh A table. Yeah, I'm gonna put all my code in urls. py because it's nicer in the demo. But obviously you don't want to do that in production Okay, so I'm gonna create a table which looks the API looks pretty similar to what you're used to from Django forms and Django models. And you have a table that inherits from table. Name artist in year columns and then we can send that to our view by creating an albums table , giving it some rows. And then we're gonna do a bind call.
Speaker 1: I'm gonna explain that a little bit later. We reload the page and you get a A table with pagination and sorting and so forth. So I'm gonna go back to the bind part here. So this thing will create Sort of an abstract definition of a table, but we actually want to couple it to the bind, to the request. Like if if you've done sorting, it needs to read that read that data from the from the from the request and apply the sorting and pagination and so forth. But normally you don't need to do this because Yeah, so you could you can use these parts like in in your existing product
Speaker 1: just putting in the context context. But I only really shines when you go for it fully. So we're gonna do that. We're gonna remove the onbind and just return the table directly. What happens here is that The IOMI middleware is gonna catch this uh IOMI class and see that it's an IOMI class, and it's gonna call dot bind on it for you and then render it And then we're gonna end up with that. I just changed the title because it was made more sense. Yeah
Speaker 1: And you also notice I got a little um uh debug panel here. So uh I'm gonna talk about those uh later but The one at the top is the jump to code, which is a very nice feature. We just click it and you jump directly to the definition of the table in this case. It's very handy, especially if you're in a new code base. So like Django forms the order here is significant uh so that you need to take care of that Yeah. So another point we want to see here is now there's no in there's no template anymore.
Speaker 1: So now we can actually delete our index. html and the base. html. We don't need it, we can just use the default one. I only comes with the bootstrap, foundation, semantic UI water uh styles by default. So in this case we're just gonna use the default uh bootstrap. You can also define your own styling which we do at our company where we had a have a proprietary design system. Now you can also simplify this even more by using the as view function. So we can move this title and rows attributes up to the
Speaker 1: class meta. So you you see this class meta pattern in in Django a lot for forms and for for models. In Django normally it means Here's a big bucket of values and Django is gonna read from them. But if you put something else in there, uh no one's gonna care. So in IOMI uh we we like this idea mostly what we don't like is when you make a spelling error here you don't get an error message. So in Iomi these are actually passed as arguments to the constructor of this table. Which means that if you make any spelling mistake, you're gonna get an error directly. It also means that writing it here and writing it here
Speaker 1: are actually the same thing with some caveats because this is the default value. You can override it later by writing something else and this will have priority. We'll see why that is actually pretty handy later. And then we just do albums table and dot as view to get the view So then if you look at this, you might notice that this albums table is the name, an artist, and a year. Which if you go to the model and look at an album, it's name artist year, that's the same.
Speaker 1: The title is albums, which is just a plural model name Rows is just all. So it's like all of this is redundant , really. So we'll actually we and we do have features for that. So the next step is gonna use That feature. So it's gonna use create a table, and there's an auto sort of namespace here. We use the same double underscore syntax for separating namespaces as Django query sets, but in Naomi it's it's like a much bigger, more fundamental concept. You're gonna see a lot more of that. So in this case There's a configuration thing which means that like auto-generate the table based on some things in this case. And in our case we want to just pass it the model
Speaker 1: album and then as view. So that's one line of definition. And you get the table. So that's nice and all. But we would like to be able to create a nicer index page, right? This is this is not a good index page. We want more information here. So another goal of Iomi is to be able to create a big complex page by taking a bunch of parts and like throwing them together. Like you want it to. And we really want that to be really simple. You should be able to take any type you need and just put it in there.
Speaker 1: So we're gonna do that now by creating a new index page It's gonna look like this. You have a title, some little help like hello text, and then three three tables where the pagination doesn't affect the other tables. And same the same with sorting. So the code for that is You create an index page in this case and we inherit from page. You create a title. In this case HTML is a little sort of URL builder feature to make this a little bit nicer. And then you can just
Speaker 1: throw in some some text. If you do this is gonna be escaped properly, but you can do mark safe on it and it's gonna uh come out. Yeah, marked safe as you would expect. And then I create three tables with auto model, artist albums and tracks, and page size set to five because like it's 40 by default which is a bit much if you have a lot of tables. And the old albums page we moved off to another URL, albums, and then we make a specific page for artists and tracks because just one line. We can go to those uh like just go albums and that's the albums
Speaker 1: uh page I'm gonna build a little uh artist page. You want normally you want a page for for one artist, right? Which albums they have and then and the name of the artist and so forth. So we'll build that when making it I'm gonna use function-based views because they compose nicer with Iomi uh and just I think compose better in in general. So we have an artist page, you get the the name of the artist here. You you just get the object. And you create an artist page, which is the title of the name of the artist, and then what albums and tracks they have
Speaker 1: Oh yeah, and uh it's in you just add the URL definition like like normal Django. Then we can go to that artist slash du which is nice and short to type. So there's there's the albums and there are the tracks Now uh one part So m maybe you've seen demos like this before. I I've seen many demos like this. At this point it looks really cool because you just throw a model at it and you get a table and it's looks really fantastic. And then when you actually try to use the library, you realize that, oh, but if I have to customize anything, I have to make everything from scratch myself
Speaker 1: This is a very common use case. I've been frustrated by this many times in my career. We absolutely hate that. So we really don't want that to be the case when using Iomi tables. So we have customization of on many, many levels. So I'm gonna start with um cell format which is the sort of most sort of low level or smallest configuration you want. So I'm back on my index page. Actually let's go to that index page And I want this column here, the artist column for albums, to to link to the artist page we just built. And you can use the
Speaker 1: cell format feature. So what we do here is for the column, right? Columns artist because that's the name of that column this is the one we care about and for the cell we specify a format function So this is a lambda with a value and I used to just do format HTML and create a link. And then you have your links But this is an extremely common use case. I mean making links for cells is maybe the most common thing you want to sort of customize in it in a in a table so there's a special sort of convenience feature for that
Speaker 1: which is cell dunder URL. So we change that You can see the diff here is we used to have cell format, format HTML, and blah blah blah. And now we've changed it to just cell URL and do get absolute URL. But even this is actually the most common use case. By default you actually do want I actually we we added uh get absolute URL to the model of course. Like you see here So this is the most common use case and if you have a column that is a foreign key, you you normally want the URL. So actually we will supply it for you if you do the auto
Speaker 1: feature. So we can delete that line. And when we look up the foreign key, we'll see that it's a foreign key and we know that the model has a get absolute URL. You can check , you'll still still get uh the link So now I'm gonna fill out the app a little bit by adding a bunch of features. Yeah, I'm just gonna gonna put make the name column here for all the different things into a
Speaker 1: link Because that's very nice. So the artists table will link to the individual artist on the name column. We don't know this by default, so that's why you have to do that. Same for albums. And on the specific artist page, we're just gonna do the same. cell formatting or cell URL and we have an album page which is the name of the album Yeah, so we'll reload that page. You see now you have links that like we have before, but also for the albums. If you click on those, you get an album
Speaker 1: See the name of the album and what artist it is and what tracks are on the album. You get these links in in various places. So another thing you want to do is have filters. So we want to add some filters to this. So I'm gonna add I'm gonna add this. I've added this filter just sort filtering on the name. So if I write du I'll just get D U and if I write 13 here I'm gonna get 13 and tracks I'm gonna write I don't know Miss something and then get the ones with mystery in the title.
Speaker 1: And uh I also have uh a drop down here for choosing the artist So this is it doesn't look super impressive right now because I don't have a hundred thousand artists, but this is actually going through an automatically created Ajax endpoint. Which goes through the same URL pattern. So if you do access control, you know that you're passing through the same access control code, which we actually use a lot at work. because now we only need to uh to check one code path for uh permission problems or uh like auditing Plus, it's just less code to match. So you get this uh drop down for free that's
Speaker 1: paginated and select two. Nice way, nice things. I'm gonna show you the code for this. So again we had we use this double underscore syntax to sort of dig down into the configuration for the specific thing we want. So columns, Dunder Name, Dunder Filter, and Dunder Include. And include here means turn this feature on. So turn on the column or turn on the filtering. So we turn on filtering for name and year and artist. But you notice that I've turned off this field thing here. So that means that there's uh there's name artist, but there's no year here
Speaker 1: Because I turned off the field, which is the part of the form here. But it's still available in the advanced search So if I switch to the advanced search, there's a query language here where I can use the The year as a filtering, and if I expand the show help, you can see available fields are to search for are name, artist, and year And it supports less than equal, contains , I can do some date filtering. It supports and or parentheses and so forth. which is really nice uh when customers want something a little bit special or or like your your staff internal staff users
Speaker 1: Yeah, so I mentioned in the start that we also have a form library So they're separate from Django forms. We tried not to write our own form library, but we ended up in the bad spot anyway. Because we needed a lot of features that we tried to bolt onto Django forms, but we just uh couldn't really do that. So we'll start to use those by adding add and delete features to this view. I'll remove all the filters Go to add and edit. Let's see where we are. Yeah. So on the index page on the albums
Speaker 1: table I'll add an edit and a delete column which means I just just do columns by the name of edit and the column dot edit and column delete here And then I reload the page. And we get edit and delete columns. Why is it yeah Like that and then I can click that and I go to the edit page. Again we have an automatic AX endpoint for the foreign keys And the edit view is our edit views are basically a read-only form, but with a delete
Speaker 1: handler for the button So we'll show where I where I uh install these views or create these views. So I've edit album which takes the artist and album I get the object and I do return form. edit and outdo dunder instance because I have a specific instance right of the album and that's my form and I'm done. Same with delete And these are just function-based views like normal, so I can just hook them in like that. But normally you don't want you don't want like on your open internet edit and delete
Speaker 1: Columns in your table, right? So we'll do some very simple naive permissions So first I'll start with adding a login and logout view that just force logins a user just for the demo so I can switch between being logged in and log out easily. And then Yeah, and the the implementation for those are irrelevant. So the columns and column delete and column edit columns now. Now we do include and we do a lambda callback and we just do request user is that And if they're if the if you're not a staff user, you don't get the entire column.
Speaker 1: So reload the thing. And I don't have the edit and delete and sorry the edit and delete uh columns anymore. But if I log in with my really bad l fake login thing and now I get them. So this this also shows the the power of Iomi where turning on and off a feature is uh It's really simple with a callback so you can have any advanced logic for turning things on and off. And their their their the configuration is in where the column is, not in some other function over there where you you you remove or add stuff, but together with the thing that you care about.
Speaker 1: Yeah. Um we're gonna do some uh some drying of this. So now now I have I have this column edit and delete, but uh these are the albums. But if I go to an artist, there's a list of albums here, but I don't have the edit and delete buttons here because I'm not reusing the same code to to create the albums list here and the albums list here. So I should fix that We're just gonna dry it up a little bit and we create a track table and we take all that configuration we had before and we just move it into the class meta Because the class meta is the same as passing it as constructed arguments, as I said before.
Speaker 1: It also makes it really easy to switch between these sort of different worlds of um yeah programmatic and declarative style configuration. And I do the same with album table and artist table And then I changed all the places where I used this or created these tables before. So before I had tracks was a table auto-model track and page size 5 and something something like that. something uh and now I just I just create an artist table with page size five uh and I just and I use exactly those classes in artist page and album page. So now I have the same functionality
Speaker 1: I have to log in here. I have the same functionality here as if I go to the artist page I get the same functionality across the site So now we have most of the crowd sort of space, right? We have delete, we have edit. We have a list, but we don't have uh we don't have create. So I'll do a create view I've just added a create album view here. Click it and you get a create view Looks basically the same as the edit view. And to make that view, I just do albums
Speaker 1: create form. create automodel album and then as view And that's it. Yeah. Oh yeah. And I actually have to add the link, right? So in the album table I add an actions create album new action and uh it's just a link basically in this case uh actors uh age ref albums create And that's that feature. So now we want to do some more customization. And I want to show Show that I I really mean it when I say you can customize the small part. We we've seen that with cell format and cell URL, but you can sort of progressively format sort of customize more and more and more and
Speaker 1: and still not throw away all your old work So first we're gonna do uh cell template. So we did cell format before, but you can actually do cell template, which is a more sort of powerful feature. So for this index page where I'm gonna change it a lot now. I'm gonna I I removed all the other tables. I only have one table now. It's the albums table And uh it's based on the albums the album model as before. And I add a new column called album art. After equals none means that this table will
Speaker 1: not try to read any attribute from the row. Because normally if you do a Just to create a column, it's gonna try to read in this case album art as a property, right? Uh from album, but album doesn't have a property like that. So I turn that thing off And then I do sell dunder template to specify template. I could have put that in a file. If you just give it a file name here, it's gonna use the the Yeah, load it like a Django template, but I'll inline it here for demo and I have to create the TD the table cell And I create an image tag. And I've already prepared all the these things so they're uh available And then you get Album
Speaker 1: arts in the columns here. So that's that's a start. It's a little bit nicer, right? But I want I want more. So we're gonna we're gonna do use a feature called row template. So I'm gonna customize the rendering of of a row. And I'm also going to change the the rendering of the entire table. So we're gonna see how that looks. So I'm gonna say the tag for the table is not the default HD It's a table anymore, but a div. The header, which you normally have in a table, right? I'm just gonna turn it off by saying the template is none. I'm gonna turn off the tag for the cell and then I'm gonna say for the for a specific row
Speaker 1: use this template instead and this is a bootstrap card Yeah, it's not so important what it contains. And we reload the page. You get this. Right, it needs some fiddling with so it looks really good. But I think this is an okay index page for a for a prototype you built in 10 minutes, right? instead of the filtering and pagination uh like before because it's a full table it's just have a customized rendering Yeah, I see your questions on the chat. I'm I'm gonna go come to that.
Speaker 1: Yeah , I'm gonna check what my time is. Ah, I'm very good for time. Cool. Um I'm gonna talk a little bit about performance here. So I've installed the Django debug toolbar, if you can see in the settings. And we're gonna look at uh look at some of these pages. So you can see here that uh there's only two SQL queries And it's doing an inner join on something, something, something here. And uh so what's what's gonna happen is uh Iom knows that you want to render uh the artist and the the artist here.
Speaker 1: So it's gonna do an a select related for you automatically. Because that's what you want. And if it's a many to many relation, it's gonna do a prefetch related for you automatically. But it can't always do that. So if I go to yeah, if you go to albums, for example, it's gonna be the same as this. But if I go to tracks, for example. That's like a little bit slower and you're gonna see you get the the normal n plus one uh Django problem here So if we jump to the code. So the the the solution here
Speaker 1: is to yeah to give it a better query set that it can start off. And you do this by doing instead of auto model, you do auto rows Right? I still need a model to do the create all the columns automatically and figure out what the title is. But from a query set I can get the model. So you just have to specify out of rows. And in this case I just want to do select related album Dunder Artist because I was using that to build some links on the page. And then suddenly you go back, you reload the page, and it's fast. I don't know if you know this, but two queries with the unit job. Like so so also another thing here is
Speaker 1: we want customizations on all the levels. We don't want just the automatic case to be super nice and simple, but we want the little bit fiddly special cases to also be very nice and simple. That's a very big design goal Yeah, and then um We have another little feature. I'm just gonna show it a little bit quickly. There's a menu component in Iomi where you you create a menu declaratively like this and the URL is defaulted to the
Speaker 1: artist slash and then you can shoot in some CSS here. Actually I didn't talk about that so much. And if I go to the index page, you'll see my menu Here because I I put it somewhere here in the index page I just declared my menu If you want it on every page, you'll have to do something different, like putting it in a context manager or something. But just for this demo, it's it's fine. Yeah, I want to talk about a little bit about customization here. So you get this atters dunder class is something. So
Speaker 1: In order for do customization here, I can shoot in a specific HTML attribute straight into the thing I want. So in this case, for the entire menu, I look up the I I go into the attributes, HTML attributes, sort of namespace, and I want to fiddle with the class and that's uh handled specially and I want to add the CSS class fixed top and I set it true and then that's why it's on the fixed top because that's the name of the bootstrap slide If I remove that line , both those lines and wait for the restart , it's gonna be fixed here, which
Speaker 1: is not so not so nice. I can also shoot in other configuration here like style, something, something, something, or any other HTML attribute I want. So yeah now comes the sort of piste de la resistance of this entire thing So I have a create, I have an edit, I have a delete, I have a listing, I have filtering, I have a menu. All these together and they're very powerful and they can be automatically derived from the models. So if I just take all these together and hook them up
Speaker 1: just right I can make an admin, a full replacement for the Django admin. So we did So you install it like so, you create an uh uh you inherit from the admin class. Well you don't need to do this, but you want to put your configuration here later probably. And then you just hook it up. I only admin include my admin URLs. Now I have an admin. I'm just log in here I will go to Iomi admin. And I have an admin replacement. And with uh Like I have a bulk
Speaker 1: delete and uh and stuff. Delete and edit and create Yeah and another cool the the really cool thing I think about uh about our um our admin Is it has the same configuration language as your normal views if you use Iomi. So there's like there's a configuration sort of language for IOMI and it's the same for the admin as for your normal views. And now I'm gonna show uh why that's really cool. So say I want to I want to change the name here here the the the header name
Speaker 1: on this column. Now we can use this pick feature here. I'm just gonna pick that one and I can see it's parts, standard, list, supernot, artist, columns, name, and header I don't care about actually Because I'm not actually gonna configure the header. So I'm gonna do this. Then the display name for this column is foo. I save it, I give it some time to restart. And now it says foo here So we see that this configuration language is the same. So here's the same configuration as you you if you created that thing yourself.
Speaker 1: Columns, name, display, and info. This part is to make it specific to this specific list. You can also ink uh do uh other crazy stuff like You can do columns, maybe sell dunder, I don't know, actors, style. background equals mm I don't know red. Black doesn't seem like a good idea Uh artist has nothing that's set. Sorry, I I removed the name. So the name column. I just shoot in a s a
Speaker 1: CSS style, just poof. Right in there. So this means that I can have I have an extremely wide variety of customizations and I can move these customizations because they use the same configuration language. It's the same set of configurations for the admin as for the normal uh sort of entire app Yeah, we have um also bulk actions. I'm not gonna show them too much, but there's here's there's uh bulk delete. So if I select these, I can do bulk delete uh or uh yeah uh select all. There's also a nice feature where
Speaker 1: uh If you do select all and there are multiple pages, we can do select all items on all pages to do bulk operations like yeah, bulk delete or modify. So this was a pretty shallow introduction to the power of Iomi and and there's a lot more I haven't shown. But I hope this presentation will spark some interest. It's a pretty new product. We're trying to get the word out And I hope you will try Iomi for your next prototype or internal tool. Yeah. Thanks for listening.
Speaker 2: Thanks so much, Anas. You've picked off part of the question host job during the talk and you were able to see some questions ticking in on on Zulib. Um I'm gonna uh Read the two questions from Sullib and then I also have a few questions if there's time for me. And the first question is from Andrew. who asks the example includes styling with bootstrap. Is this something provided out of the box? And is it possible to use with other CSS libraries?
Speaker 1: Yeah, so that that is uh supplied out of the box. Um I supplied out of the box I've implemented a bunch of them because it's it's fairly easy and it's fun. So I've implemented uh foundation CSS uh semantic UI even though that seems to be bad now which is a bit sad because I kind of like it. Um yeah bootstrap of course um water which is a very nice little minimalistic one. Oh yeah and I uh the Django admin I I implemented that style because it it was fun um It's pretty simple to implement a style yourself actually I can actually show this a little bit where you see.
Speaker 1: So uh you can actually uh sort of declare what styles you have, what templates you're gonna use for this class you wanna override some things and change what tag it has and and uh yeah um The documentation for the styling is bad for now, but there's a lot of examples at least. And we do have uh so we we use this in production because in production we have our own CSS or design system. So we need to be able to do this for us because we don't use bootstrap in production. Yeah?
Speaker 2: Is it easier to use Iomi than the Django admin? It's
Speaker 1: add it's easier to do customizations, I think. And the The customizations in the Django admin are sort of piecemeal and like you there's one hooky here and one hook here and it's like a little bit of chaos, I think. But in Naomi there's like there's a philosophy and a and a sort of a path that you can follow and it's the same for everything. And we really make we really worked on this for many years. So we think it's pretty good But obviously this is a new component. It's gonna be buggier for sure than uh than Django Admin, which is super old and very polished. Yeah. But we hope to get there. I think we can uh I think we can run past them uh
Speaker 1: with the right abstractions
Speaker 2: There has been quite a lot of wishes to extend the Jadmin uh Dango admin over time. Um Chris asks I also have a question about templates. What does editing a template look like? I don't think I understand how the inheritance tree works or how I might add some branding, a custom design and and so on.
Speaker 1: Yeah, so uh uh maybe you noticed I I have no templates. Right? I only use the built-in ones So if I go back to the code, I think. So if I declare a, in this case, the foundation style. I actually have a base template and I I specify my own. You can create your own style where you override this base template and then you can do whatever you want So that's the sort of idea. The idea is you should only need to customize some very speci some templates uh like the the the big one with all your branding and and all stuff all that stuff uh and then everything else we just sort of fill it in and and and and make it work And you say uh well I want this class for uh an input field and and and
Speaker 1: we'll do it for all your input fields depending on type.
Speaker 2: A little later today we will have uh a talk about the MBC pattern, the model view controller pattern, which indeed is is something that's close to the Django. uh mindset.
Speaker 1: It doesn't really. I mean we we uh um We re we reject the entire concept, I think. We've had a critique uh saying um you know you're you're mixing concerns. And I always ask the question, yeah okay, and why is that a problem? And I never get a reply. So if you if you have this actually the answer to this Please tell me because I think I think it's more important that things that belong that are this like belong to the same thing are are are in the same place. So if you have a field, for example, in a form You want all the customization for that field to be in that place. The HTML attributes, the the
Speaker 1: the I don't know, the template if we have one , the validation, everything should be there and not some other place, right? Not I I I hate the the clean under name of the field feature in in Django. Because if you if you misspell that then suddenly your validation isn't running anymore silently and that's just uh and it's like you have your field is here but your validation is somewhere else. Um I don't think that's a good idea. So we are mixing concerns and we're just we're saying this is sort of the declarative definition of what our view should be. in all its glory, all the the details here.
Speaker 1: And then uh and that works. We actually think it had works. very well. As I said, we've been using this in introduction since well, I mean it depends on how you count, but since 2014-15.
Speaker 2: All right. And perhaps uh I mean time is uh is is up now, but uh perhaps it sounds like there can be uh potential for panel debate. Uh especially now later we'll uh listen to uh uh both Nunne 's talk about uh the MBC and uh also Luke Plen 's talk about how to approach views in Django. So there's there's certainly room for for for different uh point points of view in this. I think
Speaker 1: I think Luke is more on my side. Uh again against cloud-based views.
Speaker 2: That's a direct question for you Luke if you're listening. And I'm also sorry that I mispronounced uh Iomi in the introduction to this talk. Of course I thought it was a very delicious uh project, so I just said
Speaker 1: No, Yok, no. It's the the black ma uh the black black Sabbath guitarist.
Speaker 2: That's what we're dealing with here.
Speaker 1: And if you read the Wikipedia page, you'll understand why it has a really nice connection to Django.
Speaker 2: Another guitarist, perhaps. Yes. So thanks once again so much for joining us. And you'll be joining us, I think, on Zulip as well. After this
Speaker 1: as much as I can. Yes?
Speaker 2: Yeah. Sounds great. Um
Iommi is a library for building HTML tables, queryset filters, forms, and composed pages. It can combine these pieces into complex views and even provide a customizable alternative to the Django admin.
Discussed at 0:02Define a table with columns and rows, then bind it to the request so sorting, pagination, and other request-dependent behavior are applied. Iommi can also bind and render the table automatically through its middleware or an `as_view` helper.
Discussed at 3:05Create an iommi `Page` and place a title, text, and multiple model-generated tables inside it. Each component keeps its own behavior, so pagination and sorting in one table do not affect the others.
Discussed at 10:02Iommi supports progressively deeper customization, including cell formatting, automatic or explicit URLs, cell templates, row templates, and changes to the surrounding HTML structure. This lets you keep generated table behavior while changing only the parts that need special treatment.
Discussed at 13:12Enable filters on selected columns with iommiās configuration syntax; it can provide text filters, related-object dropdowns, and an automatically generated Ajax endpoint. The advanced search supports fields, comparisons, contains queries, date filtering, Boolean operators, and parentheses.
Discussed at 17:00Use iommiās edit and delete columns and form helpers for existing objects, and use `create_form` for new objects. These views can be connected with ordinary Django function-based URL patterns and table actions.
Discussed at 20:14Put an `include` callback on the relevant columns and check the request user, such as showing them only to staff users. The callback can contain arbitrary permission logic, and the condition stays next to the feature it controls.
Discussed at 22:30For generated tables, iommi can infer that related objects are needed and automatically use `select_related` or `prefetch_related` where possible. When it cannot infer the right query, provide an optimized queryset with `auto_rows`, such as one using `select_related('album__artist')`.
Discussed at 31:56Create an iommi admin, include its URLs, and it provides model listings, filtering, create/edit/delete operations, bulk actions, and pagination. The admin uses the same iommi configuration language as ordinary views, so its behavior and presentation can be customized consistently.
Discussed at 35:00Yes. It includes built-in styles for Bootstrap, Foundation, Semantic UI, Water, and Django admin, and you can define your own style for a proprietary design system. Custom styles can override the base template and other component templates.
Discussed at 40:55The speaker says iommi is easier to customize because it uses one consistent configuration approach rather than the Django adminās scattered hooks. He also notes that Django admin is older and more polished, while iommi is newer and may have more bugs.
Discussed at 42:26Define a custom iommi style that overrides the base template and any other templates you need. The idea is to customize the main branded structure once while iommi supplies the remaining component markup and applies the appropriate classes and attributes.
Discussed at 43:35Note: We understand that names change, people change, and bodies change. We respect each individual's journey and privacy. If you have any concerns about a video or need us to remove content, please don't hesitate to contact us. We will handle your request with care and promptly address any issues.
Published October 13, 2024
Published October 13, 2024
Published October 13, 2024
Published October 13, 2024
Published October 13, 2024
Published October 13, 2024