Model with just one Record

How do you handle Models that should only hold one record?

For example:

class FeatureSwitch(models.Model)
     send_emails  = models.BooleanField(default=False)
     create_pdfs = models.BooleanField(default=False)

As you can see this are basically settings that are changeable by the user, but I don’t want more than one Entry for FeatureSwitch.

It feel like a Model is not quite the right way to handle this.
What are your opinions on this?

You can use a CheckConstraint asserting that its AutoField primary key is exactly 1. I think “singleton” models like this are a fine solution for a certain scale.

It might make more sense as you grow to have one FeatureSwitch per concrete feature, perhaps using an integer primary key constrained to values defined in an enumeration type (see adding such a constraint on my blog). This would alllow you to have metadata per feature, such as history tracking.


I’m in a similar case.

After searching a little bit I found that this is called “Singleton pattern” as @adamchainz said.
From there I found this project

I tried it in a test project and it may fulfill your needs but I have the same feeling that creating a model with one row is not the best approach.

In my case I want to store variables (profit rates) and let the user change them in a normal view.

  • Also I want to use it in a model property. (Another wrong approach I think)

The solution we use is an implementation of Adam’s second paragraph idea.

We have a model (actually, one model per settings type) named SwitchSettings, with two columns. The first is the name of the setting, with a unique index - where the values may be something like “send_emails” or “create_pdfs”. The second column has the value. We have a second model named UserSwitchSettings that adds a third column for an “organization” field (org_id), and the unique index is based on the switch_name, user_id tuple. (We replicate this structure for each of Integer and Character values - 6 tables in all.)

It may sound like a lot, but it works for us.