Let’s attempt to create a basic Django model that allows whitespace as a valid value. Here’s an example
class Example(models.Model): title = models.CharField(max_length=100) def __str__(self): return self.title
Using the Django shell, everything works as expected:
>>> from example.models import Example >>> created = Example.objects.create(title=' ') >>> created.title == ' ' True
But if we add the
Example model to
from django.contrib import admin from .models import Example @admin.register(Example) class ExampleAdmin(admin.ModelAdmin): ordering = ('title',)
And then try to create the same model via the Django admin, using an empty space for the title, we receive an error:
blank=True to the
title property makes the result even more confusing:
class Example(models.Model): title = models.CharField(max_length=100, blank=True)
The model will be created, but the
title property is empty!
The Django admin is doing something hidden and non-obvious when creating the example model’s admin form: it’s enabling whitespace stripping by default! This stripping process removes our whitespace character and - in the case of
blank=False (the default for fields) - fails validation!
This default can be seen in the keyword arguments of the form
CharField that the Django admin uses to represent the
title model field.
Even worse, it’s not clear how to change this behavior. Adding a
strip=False keyword to the model
CharField results in an
unexpected keyword argument error. We could build a custom form for the admin, but we’d be re-creating an entire
ModelForm to change a single keyword of one property. The
ModelAdmin has a property called
formfield_overrides, but since it operates via classes, we’d be altering the behavior of all
CharField inputs - and still need to create a custom field input class!
The easiest solution is to override the behavior of the
admin.py, which determines which form class should be used to represent each model property. We just need to add
strip=False to the field keywords when it encounters our
@admin.register(Example) class ExampleAdmin(admin.ModelAdmin): ordering = ('title',) def formfield_for_dbfield(self, db_field, request, **kwargs): if db_field.name == 'title': kwargs['strip'] = False return super().formfield_for_dbfield(db_field, request, **kwargs)
Success! The admin has an undesirable behavior, and that’s where our override lives - no changes to