DEV Community


Django Admin color picker

maco profile image Mackenzie Originally published at ・2 min read

When I add a new model to the Django app at work, I try to make sure the results in the Django admin have good usability, too. Just because it'll be mainly developers (and a few project managers) seeing it doesn't mean I can neglect usability. Consequently, I spend some time on hacking the Django admin. My manager says I've been making it do things he didn't even realize were possible.

The most recent thing I did was add a color field to a model. I considered Django Colorfield, but there's an open issue about it using GPLv3-licensed code while being MIT-licensed. 😬  So, I dug around a bit.

Basic color picker

First, I set up the model to have a primary_color that's a CharField of length 7, to accommodate a standard"#FF00FF" RGB HEX code.

class MyModel(models.Model):
     primary_color = models.CharField(max_length=7, default="#FFFFFF")
Enter fullscreen mode Exit fullscreen mode

Then, I found a StackOverflow answer that pointed out that the Django docs include how to override the widget used for a form element, so you can change which HTML5 rendering is used for <input> fields. Cool! So I just needed to add a like this:

from django.forms import ModelForm
from django.forms.widgets import TextInput
from myapp.models import MyModel

class MyModelForm(ModelForm):
    class Meta:
        model = MyModel
        fields = "__all__"
        widgets = {
            "primary_color": TextInput(attrs={"type": "color"}),
Enter fullscreen mode Exit fullscreen mode

and update the to use it:

from myapp.forms import MyModelForm

class MyModel(admin.ModelAdmin):
    form = MyModelForm
Enter fullscreen mode Exit fullscreen mode

and I'd be all set, right? Indeed, it did now show me a filled-in color block in the admin!

Adding a tooltip

But I still wasn't happy. I wanted a way to see the HEX code for the color just by looking at it in the admin. With the HTML5 element's behavior, you have to click on the color block to get a pop-up color picker and go from there to find the HEX. In Chrome on my Mac, I had to click two more times to get it to HEX mode. Ugh.

So, I dug around some more. I wasn't able to find a way to display the HEX alongside the color block, so I decided to try for putting it in a tooltip. I needed a way to get the instance of the form field, so I could read its value. With further searching, I stumbled upon a mostly-unrelated StackOverflow answer that mentioned self.instance. Great, now I just had to figure out where self was accessible from in ModelForm. Almost there! After consulting the Django docs to see which methods have access to self, I landed on this solution. In that same MyModelForm class in, I added:

    def __init__(self, *args, **kwargs):
        super(MyModelForm, self).__init__(*args, **kwargs)
        if self.instance:
            self.fields["primary_color"].widget = TextInput(
                attrs={"type": "color", "title": self.instance.primary_color}
Enter fullscreen mode Exit fullscreen mode

This grabs the value of the color field and sets it as the title attribute on the element. Title attributes display as tooltips in the browser.

Discussion (3)

gregorgonzalez profile image
Gregor Gonzalez

So simple solution! html5 has many advantages but hate to struggle with those details, I always end up doing things with javascript 😅

maco profile image
Mackenzie Author

I’m from the 90s. As far as I’m concerned, Javascript is a last resort!

gregorgonzalez profile image
Gregor Gonzalez

Yes, like everything "it should". Where I work we must take into account old browsers (including Internet Explorer) and even smartphones from 2007. So javascript ends up being a multiplatform standard.
I thunk, it depends on the project, it depends on what they decide, I don't make those decisions.

Forem Open with the Forem app