Django ORM | Ошибка в применении SingletonModel

Есть необходимость создать динамические настройки сайта для хранения телефонов, адресов, социальных сетей и прочего. Данные нужно хранить в БД, работаем мы с ней через ORM. Следовательно, нужна модель. Модель для хранения этих настроек. Также очевидно, что в этой таблице должна быть одна единственная запись. Т.е. наша модель должна реализовывать паттерн Singleton.

Далее представлено мое решение с пояснениями.

Абстрактная модель SingletonModel. Она реализована в обычном python-пакете, т.е. НЕ в приложении.

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):
    # display_list, display_list_links и inlines...
    ...

    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

Как я понял, где-то происходит попытка доступа к таблице common_info_sitesettings в момент, когда этой таблицы еще нет. Честно, я не понимаю, в чем проблема. Я пробовал вынести реализацию SingletonModel в отдельно приложение, которое регистрировал в проекте. Пробовал перенести SingletonModel в один модуль с SiteSettings. Тоже не сработало. В общем, не понимаю, в чем ошибка. Но мне все же удалось запустить миграции, но не так, как мне нужно.

Когда в классе регистрации модели (в SiteSettingsAdmin) в инициализаторе я заменил это

    ...
    # Создаем дефолтный экземпляр настроек при
    # первом запросе к странице с настройками.
    try:
        SiteSettings.load().save()
    except ProgrammingError:
        pass

на это

    ...
    # Создаем дефолтный экземпляр настроек при
    # первом запросе к странице с настройками.
    try:
        SiteSettings.load().save()
    except Exception:
        pass

у меня все миграции запустились, однако в админки не было доступа к созданию настроек сайта (т.к. я отключил эту возможность). По идее, при первом запуске должен был создаться пустой экземпляр модели SiteSettings, т.к. эта логика унаследована SiteSettings от SingletonModel здесь:

    @classmethod
    def load(cls):
        """Метод загрузки единственно экземпляра модели"""

        # Если нет ни одной записи, возвращаем новый экземпляр.
        try:
            return cls.objects.get()
        except cls.DoesNotExist:
            return cls()

Однако этого не происходит...

В общем, прошу помочь вас разобраться в этой проблеме, либо же показать, как правильно реализовывать Singleton для моделей.

Спасибо!

Вернуться на верх