Singleton Model in Django
Table of Contents
My understanding of a singleton model is one which allows you to insert only a single record to the table. This is usually used for models that hold settings.
Another form of this idea is the representation of a model where only one instance can be set as 'active' or 'default'
There are a number of ways to achieve this, but the way I used recently, which uses GeneratedField from Django 5.0 felt more elegant to me. Here it is:
for settings:
# models.py
from django.db import models
from django.db.models.fields.generated import GeneratedField
class Settings(models.Model):
send_emails = models.BooleanField(default=False)
min_score = models.PositiveSmallIntegerField(default=0, blank=True)
_key = GeneratedField(
expression=models.Value("a"), # can be any constant value
output_field=models.CharField(),
db_persist=True,
unique=True,
)
Thats all. After a record is created, subsequent creation attempts will fail due to the unique constraint. Next, for cases where there can be only one default/active record:
only one active/default:
# models.py
from django.db import models
from django.db.models.fields.generated import GeneratedField
from django.db.models.functions import NullIf
class Settings(models.Model):
name = models.CharField(max_length=250)
is_active = models.BooleanField(default=False, blank=True)
_is_active = GeneratedField(
expression=NullIf(models.F("is_active"), models.Value(False)),
output_field=models.BooleanField(),
db_persist=True,
)
class Meta:
constraints = [
models.UniqueConstraint("_is_active", name="unique_is_active_true"),
]
This exploits the way unique constraints are ignored when a column is NULL.
NullIf
sets _is_active
to NULL when is_active
is False. So the unique constraint is only active when is_active
is True.
Hence multiple records with is_active
set to False can be allowed, while only one record with is_active
set to True is allowed.
PS:
Different databases have different requirements for GeneratedField, which should be reviewed carefully beforehand