Pushing The Pony's Boundaries - Django Admin Customization by Ola Sitarska

This video features Ola Sitarska at DjangoCon US 2016 in Philadelphia, Pennsylvania, USA.

Pushing The Pony's Boundaries - Django Admin Customization by Ola Sitarska
0:28:59
Published August 10, 2016
1,991 views

DjangoCon US 2016 - Pushing The Pony's Boundaries - Django Admin Customization by Ola Sitarska

  1. Short introduction
  2. Run through available extension libraries and what’s possible in them: - Django Suit - Grappeli - Django Admin Tools
  3. Quick run through available Django Admin options. - list_display, list_filter, list_editable, search_fields, ordering, sortable - readonly_fields - raw_id_fields - fieldsets - actions
  4. Customizing Django Admin on your own. Let’s create a super custom Django Admin together! The case study of DjangoGirls.org website, that supports a management system for various users who should be able to only manage pages they’re assigned to. - Limiting objects to users - Displaying computed fields in list page - Limiting add/edit forms for different types of users - Automatically saving information per user - Custom actions
  5. Summary - Instructions where to look for more information - Improve Admin (code.djangoproject.com, open source wohoo!) - Mention about Django Admin 2

This talk was presented at: https://2016.djangocon.us/schedule/presentation/53/

LINKS:
Follow DjangCon US 👇
https://twitter.com/djangocon

Follow DEFNA 👇
https://twitter.com/defnado
https://www.defna.org/

Summary

Ola Sitarska explains how Django’s admin is assembled from the `AdminSite`, `ModelAdmin`, and `ChangeList` classes, with URLs and views generated dynamically rather than defined in conventional files. She demonstrates practical customizations from the Django Girls admin, including object-level permissions, filtered querysets and forms, read-only archived records, custom list columns, images, and bulk actions. Her main argument is to use the admin to reduce routine work and improve staff workflows, but to stop customizing it when a separate view would be simpler; custom views can also be added inside the admin so users retain a single interface.

Key takeaways

  • Django admin is driven mainly by `AdminSite`, `ModelAdmin`, and `ChangeList`, which dynamically construct routes and views.
  • Override `get_queryset` and `get_form` to restrict users to the objects and fields they are allowed to access.
  • Useful `ModelAdmin` options include fieldsets, list display links, editable columns, radio fields, save-as-new, ordering, and action-bar placement.
  • Custom methods can add computed columns, statuses, images, and bulk actions to the changelist.
  • Archived records can be made read-only for ordinary users while remaining editable by superusers.
  • When existing admin views become harder to customize than a new implementation, add a custom admin view or build a separate interface instead.

Summarised automatically from the transcript.

Transcript

5,389 words · auto-generated Show

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

0:00

Speaker 1: Come on, no.

0:14

Speaker 2: So hi hi one. I'm really excited to be here. It's my first DjangoCon US actually. I've been doing Django for seven years, but that's my first one. I um so I'm really excited to be here and it's been a long trip from Philly, which we landed at 1 a. m. this night uh today And I know it's also been an exciting and really long day for you. So really thank you for being here and for hearing my talk. And now it's just only me standing before between you and the awesome bowling party So let's get started. So we're gonna start with a story. So I have a little special bond with Django Admin. So this is really like the first feature that sold me on Django and convinced me to switch from from PHP to Python overnight. I was like I was uh so it all started when I was fourteen and I spent my days playing with like

1:02

Speaker 2: games in the internet and uh and I built this I helped build this game that um lets you carry a virtual your child for real next nine months. So that was the game and the first feature I wrote for it was actually an admin interface. and um and I was I just learned PHP on my own and that's uh that's how the story begins. And a few late few years later I knew the PHP a little bit better And but I still spent like afternoons and holidays building really extensive admin interfaces so people could actually manage the game. And that was frustrating because I always felt that I could be I'm kind of wasting my time where where I could be building a better way to, you know Change a diaper on your virtual child. So then out of nowhere um friend showed me a uh Django admin and told me it's actually just created

1:48

Speaker 2: mostly out of models and you don't have to do anything and I had no idea what Python is, but at this very time, seven years ago, I knew I was old and this is what I'm gonna be writing in now So today I'm gonna share with you a little bit of secrets I learned in seven years of building admin interfaces with Django. Uh so as J mentioned, my name is Ola. I work with awesome friends at Potato, uh which is an agency based in London, also San Francisco and Bristol. Uh some who also generously paid for my stream. trip all across from the other side of the pond. Because I come from Poland but I also live in work in London now. I'm quite involved with Django So I helped organize few Django cons in Europe

2:33

Speaker 2: and started Django Girls together with Ola, who is sitting here, and also named one of my um cats Django. So yes. Uh so that's all my night shift and during the night I work as a senior Django developer at Potato. So back to admin. Today I want to talk about two things. So first we're gonna start with the insights of admin and learn a little bit how this event works. And then we are gonna move on into the magic tricks. And I will show you a little case study of how we build Django Girls admin and what tricks we used to go from like this very usual Django admin that you can see on the left, which is actually an old screenshot of the old Django uh CSS to this new shiny uh that we are using right now and you can see on the

3:21

Speaker 2: left Right? Uh so let me dive right into the first part. Uh so that's the dark and mysterious first of how Django admin actually works. So Django admin exists since the very first synchronization of the Django framework. And let's get straight into the chase. The Django admin is one of the most mysterious and uh harder to figure out uh parts of the Django code base. Mainly because of it's quite um incredibly good backwards compatibility. So it hasn't changed for so many versions of Django and it works yeah despite the fact that Django changed so much in the last couple of years. If you ever build a Django app, probably imagine that Django Admin is just something uh different than usual Django applications. So it probably has some URLs

4:06

Speaker 2: that belongs in the URL spy file. It probably has views in the views Py file and maybe some models in the models file too. Well it It would be probably hard to be more wrong about that. The current state of affairs looks so much different from what you could imagine of how the admin is built. So let's take a look. The Django admin basically contains three main classes Each of them is at least 500 lines long, something like that. These classes are admin site, which is basically the basic configuration class of your admin site. You can have multiple admin interface instances in your application and all you have to do is just set up another instance of admin site class and include the URLs. So for example, if you would like to have a different admin for

4:51

Speaker 2: like completely different admin for some parts of the user of users like students and a different admin for teachers, that could be accomplished with that. Then there is the model admin class, which is the class you're most familiar with because that's the class you extend every time you want to create an admin for your model And the definition of this class will give you a picture of how big it is. So model admin class encapsulates all admin admin options and functionality for a given model. This takes care of everything and it's almost 2000 lines of code. And the third and last class is changelist, which takes care of displaying and managing the view with the list of objects in the model. So if you click on some model, you

5:38

Speaker 2: see this list of objects you created in that model. You can search it, filter it And things like that. So there is no URLs, there is no views, and it looks like nothing like you would expect. So to fully understand how admin works, let's go through some code and see if we can find something interesting So yeah, just as I said, the admin site object encapsulates an instance of the Django admin application, and that's ready to be hooked into your URL URL conf So at the end of admin site class class definition, you can see this uh one little bit, which is a line that defines admin site. It's a default instance of the admin site, which you use when you actually Do this so you include the admin in your URLs. In your main main URLs, you usually have to just uncomment

6:25

Speaker 2: this line in Django. So this is the class you actually use Of course, if you want, you can also create an additional admin, just as I said, just by creating another instance and plugging it into your URL's config file. So if you want to have a more awesome inside, you can just do it like this and include it in the same URL spyle. So I but I already told you there is no URL spy. So how does it actually work? If you take a look into the source, you will see that the admin site class has the property called URLs, which is basically executing the getURLs method. Going deeper, if you look at the get URLs method, you will see that actually dynamically creates all of your URL URLs. So they're not all written down, but it

7:12

Speaker 2: kind of creates them as it goes, as the uh function is executed. So it creates uh uh like the admin site wide URLs, like the direct things to like the login, to log out, password change. And then um but you already heard that there is also no ViewSPy. So all of these views that would normally be based in the view spy file are actually methods on that same class on the admin side class. As you can I hope I maybe the highlighting that I did is is visible here And the second part uh of the URLs is created dynamically and consists um of URLs to each of your registered model. So if you've got five models, it's gonna loop through this registry

7:57

Speaker 2: and create uh URLs for each of these models. models. And so it looks through them, appends them to the URLs pattern, gets the app label, model name, and includes the URLs for that model admin class. So, which brings us to the next important part of what admin site does. And that's the model registry. So models are registered with the admin site using the register method. So every time you do did admin site register in your code, which was usually in admin pi file, you actually use the admin site instance again See 1. 7, you can also do it faster, so you don't have to um you can uh do it faster without repeating the whole line and you can just Repeating actually the call uh out

8:42

Speaker 2: for admin class name, but you can just use the creator uh and that will take care of registering the model for you One thing I found out I found out when I was actually preparing this talk was that you can also if uh if you just want to use the The model admin class without overriding any of the options, you can just mention it like that. So you can don't pass the author admin name and don't create it And probably even more surprising thing is, which I don't think is probably a good pattern, but you can define the options in the registration. So you can skip registering the creating the outer admin class, but you can just register those options as parameter The register method. And the last thing that can be interesting here is the ability to change some basic configuration

9:30

Speaker 2: things in the admin side. So there is not many important bits except a couple of lines in the beginning. beginning of the file that can define how the admin is, what's the header of the admin, was the title, it was displayed in the H1 tag, on every Django admin page, or even the index page title displayed at the very top of the admin screen. So that's admin side. And now the model admin class, which is the monster in the closet. And model admin is Almost 2000 of lines that lives in Django country admin options file. And they didn't lie when they told you that it actually does everything for any given model So now we kind of got one double deeper. We've got the admin site, which is the whole

10:15

Speaker 2: admin, and then we are only looking at admin for specific model So same as before, you can notice that model admin also have the get URLs method responsible for the routing and all of the URLs. And it goes it it it works the same way. So it basically It creates all of the URLs dynamically and it doesn't uh list every one of them separately. So all everything you can imagine except maybe filters live on that model admin class. All views, all responses, URLs, and utils are just the methods of on this model admin class. However, uh this class make so it's quite a big class, but it makes it quite easy to overwrite things And as yeah, you will notice later in that talk, we'll be actually exercising this opportunity very heavily.

11:01

Speaker 2: I'm not gonna go for the whole class here because we could probably sit here for another couple of hours It's very well documented, so you can look up everything on Django documentation. But I'm gonna tell you about uh a little bit about my favorite things in this class and things that I discovered quite late and I was surprised that so easily So first one is the actions on top and actions on bottom. These are the flags that you can set to they're true or false And this defines uh uh where the action bar sits. So for example, this action bar at the bottom here uh Which says action and you can then choose action and click go. So you can define whether it's visible on the bottom, on the top, or both Which was quite a surprise for me because I often used to have like a long list and then you check all of these boxes and you go to the bottom and the action

11:50

Speaker 2: action stop is not there because it's in default only at the top. So you have to scroll all the way up and select it. So this way you can just kind of switch it on the quickly and and be done with it And the other parts of and I think there are guts and when it comes to dealing with huge models. And if you it can save you and your clients a lot of confusion if you spend the five minutes to structure and categorize it properly or even hide some fields that are not visible for everyone and they shouldn't be because it's dangerous to show some fields to people who are not familiar with the code base. So uh takes a couple of time a couple of it's probably sometimes hours, sometimes minutes to set it up But uh it's quite useful to um to use it. So here for example I grouped into three five

12:37

Speaker 2: field sets and I added also a description to the second one. So this way uh you can kind of highlight a field that should be uh kind of showed differently and provide more context. Or you can set the third field set as a collapse. So these are like for example additional option options so only advanced users should have access to them There's also a very neat option called List Display Links that allows you to specify which fields in the objects table are clickable and will direct you to edit the f in admin. The default of that is just the first field, which sometimes sometimes can be confusing. if you place some foresian key in there. And it's really useful to have a way to change that then. So it looks like this. So here you can also click the first name, which is Berlin

13:23

Speaker 2: or Christina or Anna, and we will also go to the edit page of the admin. And then a list editable option is another really useful thing. It allows you to specify which fields can be editable from and the changelist view. I usually use it for things like checkboxes. So I can use easily publish or unpublish selected objects. Although this option can be a little bit dangerous. And there is a backtracker issue open about six or seven years ago. That s suggests it's called number is one one three one three. That suggests that's currently not recommended to use in if you've got a lot of users. using the same admin, as one person can load the view, then the other person loads the view, the the second person changed something, the first person

14:09

Speaker 2: changed something, and then they kind of override their changes. And it's just can get messy and dangerous. So this is how it looks like. It basically allows you to edit at the position here in place without clicking on the edit button first. And if you need a different default ordering in the admin than in other places, because you can also define ordering on the model admin, but you can also do that Here and that will allow you to just have a different default ordering. The another neat and not very popular thing is radio fields that can uh you can specify a list of fields that are for Ginkies And they will show up as a radio buttons instead. So that's quite useful if you've got only a few options and you

14:56

Speaker 2: then you save your users a click to open the whole list of change of available options and only select a page The last one I think is the one I only heard about like a year ago. I was really surprised that it actually exists It's turned off in default, but uh there is a save us uh method that you can turn on and this will allow you to this will add you a new button, uh save us new. So when you are editing an object Then you can change something and without uh and instead of like editing the same object you can save it as a new object. So it's quite useful if you want to have like a base a base of one object and use it as a different one Oh that's the last thing. I have one more. Show

15:41

Speaker 2: full result count. So you know when you scroll down to the bottom of the admin page, you see the full uh count of how many objects there is in this model. This can be can get a lot very slow when you have lots of objects or when you're using a No SQL database. So it's quite useful to have an ability to turn it off So as you heard, model meaning class does have a lot of model specific things. Uh except this one. So when you disfuse when you end uh this This view when you enter the model admin and you see the list and you can filter things. This is actually handled by the change list. So if you want to change the way your objects are displayed on this list, this is probably a place to be. However, as you will see soon enough, most of the things you ever want to or need to change are on model

16:30

Speaker 2: admin class If you came to overriding the change list, you're probably a couple of steps to dip into this rabbit hole. So um yeah, let's go straight into the magic tricks and I will now show you how to uh make admin even more awesome. Django girls have been so we are going to use the Django Girls website as an example and we've been to many places already. We organized more than 170 events. Each of these events have their own website which is managed by one Django admin at DjangoGirls. org. So we are gonna take a look on the Django Ghost website. It's a very kind of basic content management system we wrote from scratch in Django. On the homepage, we've got a list of events, and when you click on event, you go to the event page

17:16

Speaker 2: Which is fully customizable from Django Admin. So this also allows us to publish websites in different languages, like on the website from Tampei Taipei or Hungary, without implementing a whole translation system. So each local or organizer of the event has access to manager and can edit her own event page without having access to also other edit other event pages. So that's quite important for us. So first thing we modify to make sure that organizers only have permissions of things they need and nothing else is building more advanced permissions. In this, uh the most important thing was implementing a way to give organizers access to only events they organize and no more. So we needed a more gradual permission system that allows us to give permission to one specific object,

18:02

Speaker 2: not the whole model. So here's how the admin looks for us. And by us I mean the Django Girls maintenance team that help organizers all over the world manage their own branches. So we've got we've seen all of the events And there's uh no need for us to to hide any of them. Uh to make it look nicer and add this nice uh helpful sidebar on the left, we use a package called Django suit Which gives you a really nice API to manage your sidebars and kind of makes it easy to click somewhere else. As an example, I'm gonna use just Yustina and Asia Anyak who organized a Django Girls workshop in Cardiff. And they uh they want to see the website in Cardiff and Cardiff only. Uh fortunately there is a nice and short way to do this.

18:48

Speaker 2: All you need to do is overwrite a get query set method in your model admin class So we've got even admin here and we uh define our get query set. Uh so we get the old query set first and then if user is super user, we return the whole thing, but if not we are only filtering it by the team that's in this uh event. It's simple. Now use the nine Anya only see their own event. So that's easy enough and now let's see what happens if they modify the event object Then they actually can see the whole thing again. So they can override a different event. So we need to kind of go around this and make it And solve it for them. So quick look into the insight shows me that we can also have a method called getForm, which does exactly what you think.

19:33

Speaker 2: It gets a form that is displayed on the screen So here we need to do the same field thing over at it again. And if a user is not a super user, we need to filter out the query set by the team. And then return it. And this way we've only got one uh one page available for Justina and Anja. So the last thing we modified when it comes to specific permissions for organizers was disabling an option to edit a page after the event took place. When organizers started to organize second editions of their workshops, they were going back and changing the old pages instead of creating new ones. So our archives disappeared and it was all messy. So we wanted to forbid them from doing that And documentation shows that there is something called read-only fields, which we've decided to use to uh

20:20

Speaker 2: to make this happen. So that was a little trickier and took me good half an hour to trying to uh hack into different places in the insides of the admin and I also learned that get it only feels uh is pretty tightly coupled with other parts but uh I finally found a way to use the new meta stuff from Jang 1. 8. So yeah if user was not a super user and if the event was in the past, then you would set all of the fields as read-only And this way, when uh w any of us in the Django maintenance team would enter this page, they would still be able to edit it, but organizers couldn't. So that's all we wanted. Then this is quite a uh

21:05

Speaker 2: next favorite thing to do is uh kind of make my life easier is creating custom fields displayed on the changelist table. So for example, we had the need to contact all organizers from an organizing team, and we didn't want to kind of go through everything and find their emails. So we wanted to display them just next to their event name. So all we do is you write in a simple method on event admin class that takes print object and displays uh displays all of the emails. So we can see that we defined the got organizers method here and also added the to list display. And then we list the whole admin uh the whole team of the event with their names and emails. And at the end, we just returned it as a comma-separated list. And this is how it looks like in the admin.

21:51

Speaker 2: So now next to the event name you can see all the organizers and just grab your emails and email them. That's easy. We also wanted to display the status of the event easily, so you do the same, but then you can also set the Boolean methods to true that will make them into this nice ticks and minuses instead of just displaying a word. There is also a way to display images in this way. So you do the same thing and you return some hot HTML And at the end you can see all of the yeah, I use my friend's face for it because that was the only image I had on my laptop. But uh you can see all of the images displayed here. Uh we kind of use it for sponsor logos or coaches photos, so it's easy. To grab. And I think the last thing I've got here are custom actions.

22:38

Speaker 2: So for example, we need a way to quickly publish multiple events on the homepage with just one click So um we've done this with uh here we can see an example of that and we've done this by just uh creating another method on the event admin that says show on page and then updates everything to Show is on the homepage true. And at the end we also need to add it to the actions list. And then it looks like that. So it's quite easy I think I'm running out of time, so I'm gonna give the last part quick. But uh so one thing I wanted to mention is to make sure that you don't fall into the trap of customizing the admin forever and um It's not always possible to do everything in it and you can kind of go into a rabbit hole of

23:24

Speaker 2: uh of just making the code so much uh hard to customize that it's sometimes just worth it to create a new page So don't use the Django admin interface as your user voicing interface for your public users because that's probably a bad idea. Don't waste too much time trying to customize something if you see that there is probably a dead end It means that some some Django admin parts are not just that easy as custom to customize as we would like to. So sometimes it's easier to back off and write a custom view But do spend some time to make your managers and admins life easier with just a couple of small tricks and tweaks to your code. And make sure your admins can break the website with too much power by giving them access to everything Uh 'cause that usually doesn't lead to good things. That's all.

24:10

Speaker 2: Thank you.

24:18

Speaker 3: Thank you so much, Ola, that was terrific.

24:21

Speaker 4: So I have gotten into that trap where we started a project and said, Oh we're just gonna use the admin, it'll be fine. We just need like one of the one of the change lists needs to be kind of customized. And then like two years later, we've got so much admin customization.

24:37

Speaker 2: Yeah.

24:37

Speaker 4: Or maybe like a year into it, we realized like we really should have just made a made custom stuff, but we were like so far into it. Have you had like experience like at what point do you kind of decide okay and then when you got to that point, did you go and rewrite everything or do you kind of keep some of it in the admin and then say for these For this workflow, we have this customer.

24:58

Speaker 2: Yeah. So I think for me the breaking point is when you actually spend much more time to customize something than writing from scratch So when you see this happening over and over again, I think it's the time to rewrite it. And I think I've only done this once to actually rewrite everything from scratch Maybe it's kind of uh it's probably um good to kind of learn how the Jangalmin works inside and actually have a read through this class span a day getting to know know this and then you'll have like an easier understanding of where to go and where not to go uh before it actually happens. I think that's actually quite useful thing to do. But mm yeah, the the writing part is kind of depends on on your password requirements and product. So it's hard to tell kind of and tell you what you should do.

25:44

Speaker 2: Uh it's your decision. But it's worth getting to know admin and see what What's possible and whatnot. How that helps.

25:54

Speaker 5: Um so uh related to that last question. Uh When you decide that the admin is not uh adequate for a task, do you like literally go and write something from scratch? Because I had to do dashboards and stuff like that for for not admin users but login users that control some kind of content.

26:14

Speaker 2: Uh-huh.

26:15

Speaker 5: And we want to have them filters. We want to have to give them uh search results and we want to generate forms automatically, you know, which is something that the admin makes very easy, but then having to write uh a bunch of views just to get search queries working or uh drop down filters working It's kind of painful and you miss the admin in that case. So I don't know if you have any recommendations.

26:38

Speaker 2: So what I usually done and I think we are doing this more and more with Django Girls now, we are adding another a custom Completely custom views in the Django admin. So we kind of still have people use it, but we don't try to customize those existing views that Django gives you, but we are adding new views to it. So for example, there is an app wrote by it's open source app wrote by Frank Wilz. It's called Django Almin Views, which allows you to quite easily add a view. to like another completely new Django view to your admin. And I think it's quite useful to do that instead of trying to customize and extend existing existing views. So we kind of uh the way we do this for example we need to I'm actually working on this currently but you uh we are kind of having some custom uh scenario when we are adding new organizers to events.

27:28

Speaker 2: We want to do something a little bit more automatic for it. So instead of um going around and hacking the creating new user for we are just adding another view that handles that. And I think that's the best way Because people keep this can still keep using the admin and you got all of the benefits of that, but you don't uh they basically don't have two places to go to to do this stuff. So I think that's useful

27:52

Speaker 3: Alright, one more question.

27:54

Speaker 6: Uh you showed the example with get uh display links, I think it was where you can have extra fields linked to edit that model Is it possible if you have a field that's a foreign key for a different model to link directly into the edit view? Um

28:08

Speaker 2: Yeah, I think so. I think what you would have to do is figure out the pattern of the URL and then Um and what's the name of the pattern in the URL? And then I think you can easily do that. That should work. So what I would do, I was just create the new kind of field. So like get um foraging key link or something and just hide the the old field and just uh use this one as a as a new field and then you could

28:33

Speaker 6: just use it as like an HTML yeah yeah okay

28:36

Speaker 2: that was that was

28:39

Speaker 3: Thank you so much again, Ola.

28:41

Speaker 2: Thanks.

Questions this talk answers

How does Django admin work internally?

The admin is built around three major classes: `AdminSite` for the site configuration and registry, `ModelAdmin` for a model’s options and behavior, and `ChangeList` for displaying and managing object lists. It dynamically creates URLs and implements most views as methods on these classes rather than in separate URL and view files.

Discussed at 4:06

How can I create multiple Django admin sites?

Instantiate additional `AdminSite` objects, configure or register models on them, and include each site’s URLs in the project URL configuration. This lets you provide separate admin interfaces for different groups or parts of an application.

Discussed at 4:06

How do I restrict Django admin users to specific objects?

Override `get_queryset()` in the `ModelAdmin` and filter the results according to the current user—for example, returning only events belonging to that organizer while allowing superusers to see everything.

Discussed at 18:48

How do I prevent Django admin users from editing records after a certain date?

Use `get_readonly_fields()` to make every field read-only when the record is in the past for non-superusers. Maintenance staff can still edit the record, while organizers cannot.

Discussed at 20:20

How do I add custom fields or columns to a Django admin changelist?

Define a method on the `ModelAdmin` that computes the value—such as organizer emails, a status, or an image—and add that method to `list_display`. Boolean results can be rendered as checkmarks and custom HTML can display images.

Discussed at 21:05

How do I create a custom action in Django admin?

Add a method that performs the bulk update or operation, then include it in the admin’s `actions` list. For example, the talk uses an action to publish multiple events on the homepage at once.

Discussed at 22:38

When should I stop customizing Django admin and build a custom view instead?

A useful rule is to switch when customizing the admin takes more time than writing the feature from scratch, especially when that happens repeatedly. The speaker also recommends not using the admin as a public-facing user interface.

Discussed at 24:58

How can I add custom views to Django admin without replacing the existing admin?

Keep the standard admin views and add separate custom views inside the admin instead of heavily modifying the built-in ones. A package such as Django Admin Views can make adding those views easier while keeping users in one admin interface.

Discussed at 26:38

Presenters

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 Ola Sitarska

More videos from DjangoCon US