In this tutorial, we will learn how to make optional model fields required in Django admin to make sure that data for these fields are populated on the creation of new records from the Django admin interface.
Understanding the Problem
Suppose you are working on a project that shares the User
model with customers and Staff. In the models, there is a field phone_number
that is not a required field because it's optional for customers to share their contact information. However, you want to make sure that each staff user should have a phone number.
There are multiple ways to achieve this. If you are totally sure that new staff members will only get added through the Django admin. Then the simplest one would be to make the phone_number
field required in the admin form.
Making Fields Required In Django Admin
I am gonna use the blog project for this example. Here we want to make the summary field required without making changes in models.
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 def get_absolute_url(self): from django.urls import reverse return reverse("post_detail", kwargs={"slug": str(self.slug)})
This is how my admin.py
file looks currently.
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',)}
In order to make the summary field required, we need to create a custom form for the Post
model. I am making them on the same file you can do this on a separate forms.py
file as well.
admin.py
class PostForm(forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['summary'].required = True class Meta: model = Post fields = '__all__'
As intended we create the custom model form and in the __init__
method we made the summary field required.
Finally, we just need to set form = PostForm
in PostAdmin
.
This is how the admin.py
file looks.
admin.py
class PostForm(forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['summary'].required = True class Meta: model = Post fields = '__all__'@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',)}
Save the files run the server and try to create a post without filling the summary field, you would receive a validation error like this.