Marijke Luttekes - How to create admin model views and stand-alone pages (...)

This video features Marijke Luttekes at Django Day Copenhagen 2026 in Copenhagen, Denmark.

Marijke Luttekes - How to create admin model views and stand-alone pages (...)
0:34:29
Published October 13, 2026
9 views

Marijke Luttekes - How to create admin model views and stand-alone pages without third-party libraries

Django Day Copenhagen 2026 talk descriptions: https://2026.djangoday.dk/

Transcript

4,915 words · auto-generated · en Show

Automatically transcribed, so expect mistakes in names and technical terms.

0:00

Speaker 1: All right. Welcome on stage, Marike.

0:02

Speaker 2: Yeah. It's my third time doing Django CPH. I always love it here. Just good people, good food, good everything. And I have five minutes more, which is awesome. I actually copied this from another presentation because who am I? Most of you I think we've already met. I'm a web developer. I used to my first love is front-end development, which um Therefore I do not do professionally, I do backend professionally. I love Django. Um do education stuff as well. Um I am by the way in the market for a remote job just saying hint hint nudge nudge although I am Dutch so I don't live here

0:49

Speaker 2: also Django software develop uh uh software foundation member um And I love the Django admin. I've always said it's like one of the I think one of my favorite things of software ever created For many reasons, I could fill an entire Lightning talk about why I love the Django app admin, which I'm not going to do now. We are going to talk about creating custom admin pages. And I think Maybe show of hands. Um have you all customized an admin with like list display or list filter before? Yeah, that's everyone. We're not gonna talk about that, which is really good because you all know it already. We are do gonna go do cool stuff.

1:35

Speaker 2: Um you're not supposed to read this by the way. Just it's small text, you're not supposed to read it. You can add like new pages to your admin to do weird stuff. For example, I have a blog page on my website, and that's basically legacy code. So it has like choices, decisions and code that dates pre-COVID. And one of them was to make my own markdown article thing instead of using Wagtail like a same person would have done. Well and one of the things is I have my row markdown in my in my form. You cannot really see it, but this is like a text field in a Django admin. But I don't always want to publish it right away.

2:22

Speaker 2: So I made a little custom page that shows the rendered markdown. You can maybe see there's a little link here and that thing is actually Right here. Trust me it works. And the other one, that's maybe a hack. I'm really proud of this one. There was a time where I didn't have really good command line access to the place where my site was hosted. But I wanted to have my production data just quickly as test data in my uh website. So I did something really hacky. I think it's hacky. I'm really proud of it. I captured the output of dumped data with string. io and just printed it here in a custom page in a text area.

3:07

Speaker 2: You're not supposed to do this, but it's really cool. And it's worked for me for like years now. It still doesn't crash, which is amazing. So basically this is just dumped data output. Code is not really interesting unless someone wants to see it in a lightning talk. Well, so how did I do that? Well first Big disclaimer, thou shalt reverse engineer. Django does not tell you how to do this. Ah. Well we've got some issues. If someone can fix this in the meantime We have the thing is the Django documentation tells you a little bit of how to create a new page-ish. My goodness. That is bright light.

3:55

Speaker 2: Hallelujah. Uh they tell you a little bit of how to create a custom admin page for a model, but the one that I did with the the dump data, like a completely separate page. You're not really supposed to do that. The admin doesn't tell you, the documentation doesn't tell you. But Django is like, meh, just do whatever the hell you want, which is amazing. So that's what we did. I'm gonna do a little bit of a theoretical list, like how to approximately do this, and in the end I do a live demo, God's willing. Because the model admin and the non-model admin pages, they are very different. Um

4:40

Speaker 2: the most Per the documentation one is one for a model. So like we all know our change list where you have like the list of objects in the admin and you can go to a detail page to add or edit a model. We're just gonna get like a new type of that page And you need any view for that. It can be class-based, it can be function-based. I've done both, and I think function-based is slightly better for this particular thing. But you can do both. I actually tried both. I've code for both if you want to see it. Um you have to extend this from the admin base site template.

5:26

Speaker 2: If you don't do this Um you're not gonna get a whole admin look and feel. You can only make a new page attached to an existing model admin And a model admin implies that you have a model, you know. And there is a function get URLs in model admin that you have to overwrite That is actually in the documentation. So so far we're still in the documentation area And the model admin has a little function inside it. It's called admin view, which is a authentication wrapper. Which we get back to. And optionally, you can add like

6:11

Speaker 2: role-based permission checks, like the default admin view checks for like, oh, are you a staff member But you can also do like a role-based action check, like if not every staff member can view every model. Basically whatever you want. And you can also do you can actually also add a little button in your ad view. I don't know if anyone remembers that there's a little history button in your Edit page like when you create or add a model in admin is a little history button. I'm sure some people are nodding here. You can add one of those too if you want to. A non-bonal admin though is very different because it's not an admin

6:56

Speaker 2: view, which is weird to say, but and like the data view that I had is not an admin view. It's just faking it but it fakes it really well so whatever that one can also have any few But because it doesn't have the the the get URLs function that we had with the model view, you kinda have to run all your authentication yourself. So you have to do the whole staff check yourself and all that kind of good stuff. Again, you are extending from base side just to get the whole look and feel. You can put it in any URLs. py This is actually a tricky one because if you have like registered some pages with a prefix in the root URL, then you might not be able to directly

7:47

Speaker 2: uh register in a sub-url. It's it's kind of something you'll find out when you're doing it. It's not really interesting. And optionally a never cache decorator. This makes sure that your page doesn't get cached. The model admin SVU does that for you as well. I've never needed it, but um sure you can you can add it. So authentication is like I said sometimes needed. You have a permission required decorator, and that's for function-based views, and you can do the permission required mix-in for class-based views In both cases you can do

8:32

Speaker 2: um permission required in this case could be a few a model. Like for example if I have a to-do app, the app is called to do and my uh what's it called? I think my model is called to-do list. Then I would say oh the permission that I need is to do dot view underscore to do list In simple admins where every admin has like every every page, this is absolutely not necessary, but it can be useful for like big managed organizations. And there is also the staff member required decorator, which is a thing you don't have to do in the model admin views because the SVU function in get URLs does it for you.

9:19

Speaker 2: But this one you have to kind of hack in with the generic admin page. It is a decorator so it kind of it gets a little bit annoying. Class-based views, but there's a function as view That you can overwrite in class-based views and just sort of heg it in. I have some code for that later. But actually the most annoying one is probably the context data that you have to add. For one because there's no documentation about it and you have to reverse engineer it from um admin slash options. py which is a huge huge module. Each admin site has a function, each context

10:04

Speaker 2: That one you just call in. So you do a super call to get context data. You add the each context in. Can anyone actually see my little pointy thingy? Oh that's good. There's a whole lot of uh values you can add to this, but there's basically four that you always have to add. And the four I I came to this because I use code that creates an exception when there's a variable missing in a template. This is absolutely optional, but I do it. And if subtitle is missing, I get an exception in my template. So that's why I add it. Almost no page uses subtitle, by the way, but You have to always add a title. That's like the one you always see on the top of the page in in an admin

10:52

Speaker 2: page. This one's really funny. There's a variable called opts. which is self dot model. underscore meta. And if you're like me, you're like, wait, that's an underscore method. We cannot do that. Django 1. 8, that's like a very long time ago, actually made this underscore MetaFing public library It does not make sense to me in my head, but it has been like this for years. So just accept that this is a public method. And there's another one, module name, which is also kind of weird By the way, ops and module name only work when you have a model, but the module name does like a cap first of the Ferbose

11:38

Speaker 2: name plural of your model. This one's kind of weird because it exists in some templates. There's an inconsistency in the Django admin templates that some templates use this one in the breadcrumbs. And some don't. So like changeform doesn't use it, the history view does use it. Basically the safest thing is just add it and copy paste from the history view and you're good. There's some other values you can add as well, like preserved filters, which uh preserves those get parameters that you get when you click on the filters in your change list. Um I didn't need them, so I didn't add them in this list. Anyway, my goodness. I'm going too fast by the way. Exp apologies for that.

12:25

Speaker 2: Anyway, God's willing we're gonna do a little bit of demoing because there's a lot of it's just easier to see. Oh, that was my lock button. Well, thoughts and prayers, my dear people. Um ah, there is one Apologies for the breeding, by the way. It's um sadly necessary to stay alive. This is a oh my goodness, there we are. I did not put a mirror up, I believe. Yes. I think I chose the wrong mirroring function. Oh, this is gonna be fun. I am I cannot see this on my screen right now. Um so the

13:10

Speaker 2: the back end of my blog and I had zoomed it a bit. It's a bit of an oldie now. So for example, I have this was actually an article about my presentation that it did here like three years ago, which is really fun. But you can see there's a little bit of what's it called Markdown there. And you have a little preview button here This is what you get when you override the change form template of a um model. And there it is. It has room for content warnings and all that. And then here's just a whole

13:56

Speaker 2: Really cool rendered thing. And I can view this without having to publish it to the website, which is really cool. I also always never do this. I'd rather just publish my article and then edit it like 20 times on the same day and then I actually it it got that bad, like my template does not show updated at times on the same day because I just do it twenty times. Kinda terrible. Um, but that's a me thing. Uh let's see where we are. By the way, I don't know if oh that is not where I wanted to go. I don't know if anyone's noticing, but my slash admin is actually called slash teapot on my personal website. Customize your admin endpoint, really fun.

14:42

Speaker 2: Um And again, like my whole data here, all in good fun. Let me see really quickly if I can change the way this thing is mirroring me because this is kind of annoying. I should not be touching these buttons during a presentation anyway use as mirror oh yeah there we are look at you this is much better So oh this one's already up. By the way, all my code is public.

15:29

Speaker 2: I'm gonna send you a like a link in the end where you can find all my stuff this one is in Koeburg my personal website but I also have a uh local test project that's on GitHub I use that for oh my goodness Where are we going? Um, I use that one for Django tests. Let's do this then. Okay. I made a little to do app. This this Django local test project is just a thing that I use for Django. Development. So there's also a huge disclaimer to readme like not for production purposes. So there is some weird stuff in there, and just accept that it is.

16:14

Speaker 2: Um can do a small one next. Let's do another one first. You can add like a Zen of Python page if you want to. Really fun. Or more cool is a an overview. of your entire list. Like I made a to-do list and has this whole inline thing. It's not really Readable, so I made a little button called full to-do list that just renders the whole thing. And what does it look like? It

17:01

Speaker 2: basically just looks No. Like. Thank you. Apologies for everyone who's now burning their eyes out. This is light mode. This basically is extends from adminbase. html and there's only two things you need to override the breadcrumbs by the way if you are copy pasting from Django which you should absolutely do Django 6. 1 changed The HTML for the breadcrumbs. I think my friends at the accessibility team had some hand in that, but it's now better. So if all your breadcrumbs break because you upgrade to 6. 1, I warned you.

17:49

Speaker 2: And basically always be copy-pasting from the history view, both the template and the view in Python. That's like the easiest way to get this all done And there's a block content where you put some stuff in. No one actually has documented exactly what kind of ooh, what kind of HTML you need to use. You kind of oh dear, that's my Go with you. Um I just sort of again reverse engineered this from existing pages, but there's always a div with an ID content main. There's always a classes module div And then you put some stuff in there. I used an ordered list for to do I geez, I needed to put that thing off. There's an ordered list here for my items.

18:36

Speaker 2: Ordered list ironically does not have styling in the um CSS. Eh, well, it isn't it's not supposed to be pretty, so I just accept that the org list looks a little bit ugly in my uh website Or I will show you another one which is oh there we go again uh data index Where is it? Oh wait, I I already had it open. Um The one with the uh this is the one with the data output from dumped data, and I actually needed a bit of the form

19:25

Speaker 2: styles for that. Which is not something loaded by default by the base side. So you can actually just load some of the extra CSS files from the website if you need to. And then you can kind of hack your entire form. This is this is actually reverse engineered from how the change form does it. I am not a fan of the HTML that happens in in in in the admin but um we're um just gonna live with that so if you think like oh there's too many diffs here yes but that makes it look like go. So again, we're just gonna live with it or make a pull request to make it better. That's like your two choice two choices.

20:11

Speaker 2: Um uh So um see if I can open This thing here. This is not the one I wanted to show you This isn't this is a very old view where I actually made a class-based view. This is not the one I wanted to show you. You can basically just put like a whole bunch of stuff in a page. Again, this is like a very normal view. This thing actually doesn't even

20:57

Speaker 2: This thing doesn't even inherit from an admin view or whatever, but you can just put all the context data in and because the template inherits from base side, that's what makes it work. But I actually did some research on what kind of base views you have to make. And oh apologies for the jumping. This is always a little bit tricky. Uh, where are we? There we are Uh nope, this was not the one that I wanted to show you. Again, apologies. the one I wanted to show you.

21:45

Speaker 2: In my Django test site I eventually just created two base views That fixed this for you. A base view for a model base or model less page, and one that inherits from it that acts like that needs a model This is actually the easiest one to show you what you have to do to create a base view. This is a view for a modelless, a base for a modeless page. There is a kind of a little ugly oh my Okay, stop doing that. I have a little class method that as view that oh that adds the whole staff member required decorator in there

22:32

Speaker 2: which is actually not something you have to do if you have a model class but I just put it in the base so this is a little bit superfluous but we're running with it There is no mixing equivalent for staff member required, which is kind of weird. So we kind of hacked it in here. And the context data, this is the important one. You get the context data from the parent, not strictly necessary here as well, but always do a super call just in case. And here you have that wonderful. admin. site. each context. This loads all the default context from the admin. And we're adding a title and a subtitle by default Otherwise my fuse will crash because there's a missing variable.

23:19

Speaker 2: Again, that is an entirely optional thing. And once you add a model to it, you need a model class. This is actually a default requirement for all model admin things. So this is like a drop in Fuel for um things that use a model and you always need a model anyway because you have you're tying this to a model admin. Uh uh see also my always futile attempts to do a little bit of type hinting in Django. Like if I ever get a wish I won. like type hinted Django or a purple dragon with golden spots on it, whichever whichever

24:06

Speaker 2: is like more r likely to happen. Um anyway, get context data. This one takes because this is a this one inherits from that base thing, so this one takes the title and sub and the title, the subtitle and the admin each view from its parent. This is why we're only calling the super get context data here. We're adding The module name and that's that weird cap first ops. vernbost name dot plural. I just copy pasted this from from the pick history view and the opts which is the self. model. meta and actually this is all you need to make a custom page which

24:52

Speaker 2: It's really funny because this took me a few hours to figure out. It's like very little code, but it it takes so long to figure it out. And I will actually show you. Where to reverse engineer this? There is in Django Contrib admin options. py You will remember this eventually. And this thing is ridiculous. Like, how many lines do we have here? I have no idea how many lines we have here, but we have many. And somewhere around line Twenty five hundred ish. There is a history view

25:40

Speaker 2: And basically anything that makes the apping go is in this file. There's too much going on, but the history view, this is like your everything you want to know is in here. Um it has for example well this is you can skip the whole patinator thing but like the whole list of stuff uh variables you can pass to a um Few are here, so the preserved filters I mentioned earlier. You can see the options here as well. Like they have some patination stuff as well. We don't do that, but here you can see the big Cap first self dot blah blah blah blah blah blah blah copy pasting is amazing people we should do it more

26:26

Speaker 2: um and it It's actually easier to just take GitHub here. GitHub was a little bit down yesterday. So thoughts and prayers We have GitHub people. Oh my god. Yes. Um, it's not so good scene but GitHub has this whole very fancy sidebar now And in everything you need to know is in contrib slash admin. There's like the templates here. You can see there's an options here. That's the one we were just looking at. Which by the way, this is absolutely ridiculous this thing is oh no sh just shy three thousand lines could be worse

27:12

Speaker 2: um and this is where you can find everything you need to um basically copy paste from. So there's templates, there's an admin, there's lots and lots of templates The change form is the one you could override if you want a little button. It's in the change form object tools You can add like the little button to the custom page in here. There's also a change from actions. html Which I always thought you could overwrite, but actually you cannot override it because it's not a block, so you cannot do a super call. So just don't touch it. That's like the short. version of it. Um and

27:57

Speaker 2: here's our kicker, the objecthistory. html Can we get rid of this sidebar? Like how does GitHub work? I have not used GitHub in months ever since I went to Codeberg. Um where are we? Yes, we are Is this actually readable for people? I prefer to use light mode on screen, but you know, it's dark mode now. Anyway, you can see here a block breadcrumbs. This is where you copy paste your breadcrumbs for. The wonderful module name is here in the third um thing like the change form template actually just uses the cap first filter right here which is

28:43

Speaker 2: Meh uh yeah, two minutes. But that's why I say copy from object history, the action list, you can ignore that. Um Um and it takes the this is the content thing, the content block, and here you can paste your copy your divs from It's amazing. I highly recommend people to just dive into this whole thing because there's just so much here. I can do like entire presentations on what is here. Which I won't because I have one minute left. Um And also I did not sleep for four days, so that doesn't help. Uh my god. I I miss my bed. I miss my bed so much

29:28

Speaker 2: Anyway, that was a short long trip through uh Django Admin. Uh oh And like I said, for those who trust me, I have a QR code. This is a QR code to oh thank you for the people who trust me in the back. This is a QR code to my Link Hub. Which has links to my Codeberg, GitHub, blog, all the things. So like I said, because part of the code base I showed you is on Codeberg, the other part is on GitHub, which is a bit annoying. But It's all there if you want to dive into it. For those hearing with us at home, it's basically my name separated by a period and the last two letters ES is the top level domain. So it's maraike.

30:14

Speaker 2: lotic. es um also most people don't know how to spell my name so also copy paste that as well from somewhere You know. And that was it.

30:32

Speaker 1: Thank you. There's actually I thought maybe we could take a question. Um or two, do you have time?

30:41

Speaker 2: I have time. Yeah? Yeah.

30:43

Speaker 1: All right. And uh nice nice tips here. Tips of Flying all around. Spanish domain names?

30:50

Speaker 2: Um it is a very expensive domain name. That thing is more expensive than multiple of my other ones together. It's it makes me cry every year I get the invoice.

31:00

Speaker 1: Okay. Um yeah, um questions from the audience here? Otherwise I I have a question uh in in in in general, um like the Django admin is obviously uh huge uh territory to cover and like a lot of people end up with this are you supposed to use it for what type of use uh uh you seem to be doing the uh safe bed y using it for yourself as a developer?

31:33

Speaker 2: Yeah I I have a philosophy in that. I think that the Django admin is for like people in a company. So it's not for your customers. So even if you're like making a website for a customer, I would give them a custom admin. maybe uh or a few trusted people in that in the client company can also go into the admin uh but technically everyone can get some use out of the admin in in a company, but you don't want your regular users in there. And it's not the most user-friendly environment. So in the end you can always end up making custom admins for your the employees of your customer as well

32:15

Speaker 1: And like um this was actually a very very good introduction just to using the admin in in general. Um I feel like it's a it's great to step into these vast projects where the admin can do like everything for a company. Uh it can also be scary. Good resource that can kind of not just introduce people to the Django admin as per the docs, but all these other great uh things we can do tricks or hacks?

32:48

Speaker 2: Github. com slash Django slash Django. No really uh that there is some stuff in the documentation, but um The Django documentation isn't really too full about that. It shows you list display, list filter, like how to customize the change list. Um I actually found only one useful article on Medium of All Places, which I regret. Um that showed me how to create a custom admin page. So there is maybe a time maybe I am the one. who has to write that manual. Like I said, there's lots of reverse engineering going through, but like the basics is in the docs for list display and all that.

33:31

Speaker 1: Got a question in the audience.

33:34

Speaker 3: So what is the craziest thing you have done with Django Admin? So I have seen people doing like charts of payment volumes. Within Django Admin.

33:44

Speaker 2: I have not done a lot of crazy things. I I thought the whole dump data thing was already a bit hacky, but um I know people who put like entire order lines, entire invoices in a custom page. I'm sure you can also put a payment provider in there because like I said, Django is Basically, Django lets you do whatever you want at your own expense. So if you want to put a payment provider in there, YOLO, you shouldn't, but you could.

34:15

Speaker 1: All right, um I think we're uh up for time and thank you for the questions. Uh and next speaker is Effe.

34:24

Speaker 2: Yes.

34:24

Speaker 1: Yes. Also

Conference

Django Day Copenhagen

October 2, 2026

Copenhagen, Denmark

Note: 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.

More videos by Marijke Luttekes

More videos from Django Day Copenhagen