Подтвердить что ты не робот

Модели Django: разрешить только одну запись в модели?

Я хочу, чтобы некоторые из моих глобальных настроек Django настраивались через интерфейс администратора.

С этой целью я решил установить их как поля базы данных, а не в settings.py.

Это настройки, которые меня волнуют:

 class ManagementEmail(models.Model):
    librarian_email = models.EmailField()
    intro_text = models.CharField(max_length=1000)
    signoff_text = models.CharField(max_length=1000)

Это одноразовые глобальные настройки, поэтому я хочу, чтобы там только один librarian_email, intro_text и т.д., плавающий вокруг системы.

Есть ли способ запретить пользователям администратора добавлять новые записи, , не мешая им редактировать существующую запись?

Я думаю, я могу это сделать, написав специальный шаблон для этой модели, но я хотел бы знать, есть ли более простой способ настроить это.

Могу ли я использовать что-то другое, кроме class, например?

Спасибо!

4b9b3361

Ответ 1

Посмотрите этот вопрос на "сохранить [настройки] в базе данных" , где ответ кажется django-dbsettings

Update

Просто подумал о другом варианте: вы можете создать следующую модель:

from django.contrib.sites.models import Site

class ManagementEmail(models.Model):
    site = models.OneToOneField(Site)
    librarian_email = models.EmailField()
    intro_text = models.CharField(max_length=1000)
    signoff_text = models.CharField(max_length=1000)

Из-за поля OneToOneField вы можете иметь только одну запись ManagementEmail для каждого сайта. Затем просто убедитесь, что вы используете сайты, а затем вы можете вывести настройки таким образом:

from django.contrib.sites.models import Site
managementemail = Site.objects.get_current().managementemail

Обратите внимание, что то, что все остальные говорят вам, верно; если ваша цель - сохранить настройки, добавив их один за другим, так как поля для модели не являются лучшей реализацией. Добавление настроек со временем будет головной болью: вам нужно добавить поле в свою модель, обновить структуру базы данных и изменить код, вызывающий этот параметр.

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

Ответ 2

Я думаю, что самый простой способ сделать это - использовать функцию has_add_permissions для ModelAdmin:

class ContactUsAdmin(admin.ModelAdmin):
    form = ContactUsForm

    def has_add_permission(self, request):
        return False if self.model.objects.count() > 0 else super().has_add_permission(request)

Вы можете установить, что это все, что угодно, см. django docs.

Если вам нужна более гранулярность, чем это, и сделайте класс singleton на уровне модели, см. django-solo. Есть также много реализаций singleton, которые я встретил.

Для StackedInline вы можете использовать max_num = 1.

Ответ 3

Просто настройте приложение GlobalSettings или что-то с полем "Key and Value".

Вы можете легко запретить пользователям администратора изменять значения, не давая им разрешения на редактирование приложения GlobalSettings.

class GlobalSettingsManager(models.Manager):
      def get_setting(self, key):
          try:
              setting = GlobalSettings.objects.get(key=key)
          except:
              raise MyExceptionOrWhatever
          return setting

class GlobalSettings(models.Model):
      key = models.CharField(unique=True, max_length=255)
      value = models.CharField(max_length=255)

      objects = GlobalSettingsManager()

>>> APP_SETTING = GlobalSettings.objects.get_setting('APP_SETTING')

Есть приложения для этого, но я предпочитаю смотреть на них и писать свои собственные.

Ответ 5

Я бы взял страницу из Wordpress и создал модель, поддерживающую настройки.

class Settings(model.models):
 option_name = models.charfield(max_length = 1000)
 option_value = models.charfield(max_length = 25000)
 option_meta = models.charfield(max_length = 1000)

Затем вы можете просто сортировать (сериализовывать) объекты в полях, и вы будете твердыми.

Постройте немного api, и вы можете быть такими хитрыми, как wordpress и call. AdminOptions.get_option(opt_name)

Затем вы можете просто загрузить пользовательские настройки во время выполнения, оставив модуль settings.py отдельным, но равным. Хорошее место для записи было бы в файле __init__.py.

Ответ 7

Изменение ответа @radtek для предотвращения удаления, если осталось только одна запись

class SendgridEmailQuotaAdmin(admin.ModelAdmin):
    list_display = ('quota','used')
    def has_add_permission(self, request):
        return False if self.model.objects.count() > 0 else True
    def has_delete_permission(self, request, obj=None):
        return False if self.model.objects.count() <= 1 else True
    def get_actions(self, request):
        actions = super(SendgridEmailQuotaAdmin, self).get_actions(request)
        if(self.model.objects.count() <= 1):
            del actions['delete_selected']
        return actions

Ответ 8

У меня была в основном та же проблема, что и исходный плакат, и он легко исправляется путем переопределения классов modelAdmin. Нечто похожее на это в файле admin.py легко предотвращает добавление нового объекта, но позволяет редактировать текущий:

class TitleAdmin(admin.ModelAdmin):
def has_delete_permission(self, request, obj=TestModel.title):
    return False

def has_add_permission(self, request):
    return False

def has_change_permission(self, request, obj=TestModel.title):
    return True

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