Answer the question
In order to leave comments, you need to log in
Django ORM | Error in applying SingletonModel?
There is a need to create dynamic site settings for storing phone numbers, addresses, social networks and other things. The data needs to be stored in a database, we work with it through ORM. Therefore, a model is needed. The model to store these settings. It is also obvious that there should be only one entry in this table. Those. our model must implement the Singleton pattern.
Below is my solution with explanations.
An abstract SingletonModel. It is implemented in a regular python package, i.e. NOT in the app.
from django.db import models
class SingletonModel(models.Model):
"""Абстрактный класс синглтон-модели"""
class Meta:
"""Настройки модели"""
abstract = True
def save(self, *args, **kwargs):
"""Метод сохранения записи в БД"""
self.__class__.objects.exclude(pk=self.id).delete()
super(SingletonModel, self).save(*args, **kwargs)
@classmethod
def load(cls):
"""Метод загрузки единственно экземпляра модели"""
# Если нет ни одной записи, возвращаем новый экземпляр.
try:
return cls.objects.get()
except cls.DoesNotExist:
return cls()
class SiteSettings(SingletonModel):
...
class Meta(SingletonModel.Meta):
"""Настройки модели"""
verbose_name = _('Настройки сайта')
verbose_name_plural = _('Настройки сайта')
def __str__(self) -> str:
return _('Настройки')
@admin.register(SiteSettings)
class SiteSettingsAdmin(admin.ModelAdmin):
...
def __init__(self, model, admin_site):
"""Инициализатор класса"""
super().__init__(model, admin_site)
# Создаем дефолтный экземпляр настроек при
# первом запросе к странице с настройками.
try:
SiteSettings.load().save()
except ProgrammingError:
pass
def has_add_permission(self, request, obj=None):
"""
Метод проверки прав на добавление.
По умолчанию запрещаем добавление новых записей.
"""
return False
def has_delete_permission(self, request, obj=None):
"""
Метод проверки прав на удаление.
По умолчанию запрещаем удаление записей.
"""
return False
django.db.utils.OperationalError: no such table: common_info_sitesettings
...
# Создаем дефолтный экземпляр настроек при
# первом запросе к странице с настройками.
try:
SiteSettings.load().save()
except ProgrammingError:
pass
...
# Создаем дефолтный экземпляр настроек при
# первом запросе к странице с настройками.
try:
SiteSettings.load().save()
except Exception:
pass
@classmethod
def load(cls):
"""Метод загрузки единственно экземпляра модели"""
# Если нет ни одной записи, возвращаем новый экземпляр.
try:
return cls.objects.get()
except cls.DoesNotExist:
return cls()
Answer the question
In order to leave comments, you need to log in
The solution turned out to be very simple and obvious.
The error was that during the creation of migrations, the object loading code was executed before the table was created in the database.
You just need to create a table in the database before migrations, and in order not to mess around with this, you can simply comment out the registration class of the model, run the migrations (then the table will be created fully configured) and then uncomment the registration class.
Here is a good implementation example:
Singleton Design Pattern Example
In your example, for example, it is not clear why to do this:
class Meta(SingletonModel.Meta):
You then inherit abstract = True for the model. But your specific model is not abstract ...
why such a construction:
self.__class__.objects.exclude(pk=self.id).delete()
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question