In this tutorial, we will learn how to show custom validation exceptions on Django admin.
Understanding The Problem
Django admin site will raise exceptions when we try to save objects with non-acceptable values. Often we need to create our custom validators and raise custom exceptions depending on the needs of the project. Like if you want the phone number to be in a particular format or you want to make sure the first name starts with a capital letter.
There are a lot of ways to achieve this but if your goal is to ensure proper validation limited from the admin interface only, then this tutorial is for you.
Note: If creating validators that remain constant throughout the app is your goal, then you should check out this article - Creating Custom Model Validation In Django
Displaying Custom Validation Exception in Django Admin
We will use the popular blog project for this tutorial. The goal is to ensure that the title of the post is in the proper title case.
Let's have a look at our existing models.py
and admin.py
file.
models.py
class Post(models.Model):
title = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=200, unique=True)
author = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="blog_posts")
updated_on = models.DateTimeField(auto_now=True)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
status = models.IntegerField(choices=STATUS, default=0)
summary = models.CharField(max_length=500, null=True, blank=True)
class Meta:
ordering = ["-created_on"]
def __str__(self):
return self.title
admin.py
@admin.register(Post)
class PostAdmin(SummernoteModelAdmin):
list_display = ('title', 'slug', 'status', 'created_on')
list_filter = ('status', 'created_on')
search_fields = ['title', 'content']
prepopulated_fields = {'slug': ('title',)}
Now to make custom validators for the admin site we need to create a custom form for our model. So in the same file or in a separate file create a form like this.
from django import forms
class PostForm(forms.ModelForm):
def clean(self):
title = self.cleaned_data['title']
if not title.istitle():
raise forms.ValidationError({'title': "Not a proper titlecased string"})
The model form comes with the clean()
method that is responsible for performing validations.
Take the title value from the cleaned_data
dictionary and run the validation through it, if it fails the raise the ValidationError
with the exception message.
Finally. we need to link our form with the PostAdmin
.
@admin.register(Post)
class PostAdmin(SummernoteModelAdmin):
form = PostForm
list_display = ('title', 'slug', 'status', 'created_on')
list_filter = ('status', 'created_on')
search_fields = ['title', 'content']
prepopulated_fields = {'slug': ('title',)}
That's it! Save the files run the server navigate to the admin and test the flow.