How to create Django Admin actions with and without intermediate page

Dan Okhlopkov
4 min readOct 30, 2019

--

I’ve spent a huge amount of time compiling all articles about Django Admin actions creation. Most of them were from 2010–2012 which made me really sad. Finally, I figured out everything I need and not I want to share “the right answers”. Enjoy.

My goal was to create a native way to launch tasks for my Django projects because built-in Django web Admin panel allows non-programmers to dive into my projects really quickly. And this is the coolest thing — not all people like to code even if they can, they like to push buttons without opening the shell. Django Admin can do a lot of basic stuff out of the box, but I wanted to add more. And I found that in Django Admin it is reeeeally easy (if you know the right python magic spells).

I don’t know the reader’s level of Django, I’ll try to give as many details as I can.

How to add Django Admin action that just runs a function

One of my projects has a playlist parsing part. Sometimes I need to manually re-parse the playlist (for example when I’ve updated the parser code after a bug fix). So I found the cool way to add a method to Django Model that can be launched from the Admin panel.

I’ll give you an example from my project. Maybe you would find more useful tricks.

# your_app/admin.pyfrom django.contrib import admin
from .models import Playlist
from .tasks import parse_playlist
@admin.register(Playlist)
class PlaylistAdmin(admin.ModelAdmin):
actions = ['parse']
def parse(self, request, queryset):
queryset.update(is_parsed=False)
for playlist in queryset.all():
parse_playlist.delay(url=playlist.url)

self.message_user(request, "Playlists will be reparsed soon")

Interesting parts:

  1. @admin.register — this is a decorator that prevents you to write admin.site.register(Playlist, PlylistAdmin). For me, it is cooler way, but not everyone agrees with me: https://github.com/encode/django-rest-framework/pull/7022.
  2. actions = ['parse'] — special ModelAdmin property where you should put the names of methods that you want to be included in Django Admin actions.
  3. def parse(self, request, queryset) — There are a lot of tutorials on the Internet where these methods for Django Admin were written outside of the ModelAdmin class. I don’t think that this is a cool way — you can “attach” these methods to the class.
  4. queryset.update(is_parsed=False) — I just change the Playlist.is_parsed field to False because my playlist will be parsed again really soon.
  5. parse_playlist.delay(url=playlist.url) — I have a Celery task called parse_playlist and in this line, I detach this task with .delay() method. Nothing special.
  6. self.message_user(…) — This is the message that will appear to Django Admin users when the parse method ends. It is cool to add there some numbers and stats on just run tasks.

How to create a Django Admin action with intermediate page to provide action params

It is cool to run tasks in the way I showed you above. But there are cases when you need to provide more data to run the task.

I needed to write a broadcast method that will send the message to some Telegram bot’s users. The plan is:

  1. Select users from admin panel
  2. Click on my broadcast action and provide with broadcast message text
  3. Press run and let background tasks do their job.

I don’t know any frontend stuff, the best web this that I’ve made is my portfolio website: https://okhlopkov.com/. But I understood that I need to create this intermediate page with form to get data from Django Admin user.

I’ve compiled these solutions together to make something that works. I’ll give you the step-by-step guide:

You will need to create/edit files of your app:

  1. your_app/forms.py
  2. your_app/admin.py
  3. your_app/templates/admin/broadcast_message.html

This is my forms.py file

# your_app/forms.py
from django import forms
from .models import Bot
class BroadcastForm(forms.Form):
_selected_action = forms.CharField(widget=forms.MultipleHiddenInput)
broadcast_text = forms.CharField(widget=forms.Textarea)
bot = forms.ModelChoiceField(Bot.objects)
  1. _selected_action — This will be used to transfer selected items data from a Django Admin Form to the code.
  2. broadcast_text — The input text of my broadcast message. I will take this text and broadcast it to my Telegram bot users
  3. bot — In my backend, I have several Telegram bots. That is why I want to select the Bot instance which will broadcast the message.

This is my admin.py file

Your action file should render the page with your form where you would add parameters to launch your Django Admin action. When the intermediate page is filled and the user pressed the “submit” button — you need to extract the params from the POST request and run your desired background task.

I’ve added the comments to the code:

Read comments between the lines

The Intermediate page

I don’t know how anything about HTML, CSS, and JS. I was really afraid of all these Django templates also. BUT I found that all hard code will be generated automatically. I also add comments to the code — I hope they are clear enough.

The Django Form will generate the form fields by itself — take a look at {{ form }}. This is the coolest part of this template. You can just copy-paste this template to create more actions. Since all important code is generated automatically, I think you can also try to use one template for all your actions — I will try to do it in my projects too.

Thanks for reading! I hope that this can help anyone. Please clap 23 times and follow me for more hacks.

--

--

Responses (3)