14đź‘Ť
An easy way is to use the setting’s name as the primary key in the settings table. There can’t be more than one record with the same primary key, so that will allow both Django and the database to guarantee integrity.
15đź‘Ť
Try this:
class MyModel(models.Model):
onefield = models.CharField('The field', max_length=100)
class MyModelAdmin(admin.ModelAdmin):
def has_add_permission(self, request):
# if there's already an entry, do not allow adding
count = MyModel.objects.all().count()
if count == 0:
return True
return False
13đź‘Ť
William is right, but I guess this is the best practice
def has_add_permission(self, *args, **kwargs):
return not MyModel.objects.exists()
As reported in the official Django Documentation:
Note: Don’t use this if all you want to do is determine if at least one result exists.
It’s more efficient to use exists().
https://docs.djangoproject.com/en/dev/ref/models/querysets/#when-querysets-are-evaluated
10đź‘Ť
Overwriting has_add_permission
works, but in the given examples it breaks the permissions system in Django(staff without necessary permissions can add settings). Here’s a one that doesn’t break it:
class SettingAdmin(admin.ModelAdmin):
def has_add_permission(self, request):
base_add_permission = super(SettingAdmin, self).has_add_permission(request)
if base_add_permission:
# if there's already an entry, do not allow adding
count = Setting.objects.all().count()
if count == 0:
return True
return False
- How to access both directions of ManyToManyField in Django Admin?
- Differentiating between different post requests on the same page in Django views.py
3đź‘Ť
A model with a single allowed row is nothing more than a perverted form of a “persisted object” — maybe even a “persisted singleton”? Don’t do that, that’s not how models work.
Check out https://github.com/danielroseman/django-dbsettings
- Django and models with multiple foreign keys
- Exposing django admin to users. Harmful?
- Monolithic or microservice concept
- Django A/B Split Testing Packages (None I've found are well-documented and up-to-date.)
2đź‘Ť
It looks like Ali Reza’s answer but you can update the existed records and return the error message to any form that uses this model. I believe it is reliable and much easy to control.
class MyModel(models.Model):
...
def clean(self):
super().clean()
if not self.id and MyModel.objects.exists():
raise ValidationError('You cannot add more somethings.')
0đź‘Ť
The following is a class I have created which can be used as a singleton class.
from django.db import models
class SingletonModel(models.Model):
class Meta:
abstract = True
def save(self, *args, **kwargs):
self.__class__.objects.exclude(id=self.id).delete()
super(SingletonModel, self).save(*args, **kwargs)
@classmethod
def load(cls):
try:
return cls.objects.get()
except cls.DoesNotExist:
return cls()
From the above SingletonModel
we can create multiple models, all of which will be having only one record
class ProjectSettings(SingletonModel):
max_tickets = models.IntegerField(default=15)
min_tickets = models.IntegerField(default=2)
...
We can access the only object of the settings model as follows
ProjectSettings.load().max_tickets
It is also possible to register ProjectSettings
to django admin
@admin.register(ProjectSettings)
class ProjectSettingsAdmin(admin.ModelAdmin):
list_display = [field.name for field in ProjectSettings._meta.get_fields()]
def has_delete_permission(self, request, obj=None):
# Nobody is allowed to delete
return False
- Using Django's collectstatic with boto S3 throws "Error 32: Broken Pipe" after a while
- Django-cms: urls used by apphooks don't work with reverse() or {% url %}
- Django Deployment: Handling data in database
- What does 'name__iexact' mean in django model filters?
-1đź‘Ť
You can rewrite the save method on your model. Whenever the user wants to register a new record, you can check the existence then, either save the record or, reject the request.
class MyModel(models.Model):
title = models.CharField(...)
body = models.TextField(...)
def save(self, *args, **kwargs):
if MyModel.objects.exists():
raise ValueError("This model has already its record.")
else:
super().save(*args, **kwargs)
You can also use validators. I prefer to use this method.
Hope you find it useful.