Модели Django: разрешить только одну запись в модели? - PullRequest
15 голосов
/ 03 февраля 2011

Я хочу сделать некоторые из моих глобальных настроек 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, например?

Спасибо!

Ответы [ 8 ]

16 голосов
/ 03 февраля 2011

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

Обновление

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

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, о котором я упоминал выше, поскольку оно делает именно то, что вам нужно - обеспечивает редактируемые пользователем настройки - без необходимости выполнять дополнительную, ненужную работу.

10 голосов
/ 02 августа 2014

Я думаю, что самый простой способ сделать это - использовать функцию 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 .

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

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

3 голосов
/ 07 апреля 2015

Попробуйте Джанго-Констанс.Вот несколько полезных ссылок:

https://github.com/jezdez/django-constance

http://django -constance.readthedocs.org / en / latest /

2 голосов
/ 04 февраля 2011

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

class Settings(models.Model):
    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 файле.

2 голосов
/ 04 февраля 2011

Вы можете запретить пользователям добавлять / удалять объекты, переопределив этот метод в вашем классе администратора:

ModelAdmin.has_add_permission (self, request)

ModelAdmin.has_delete_permission (self, request, obj = None)

2 голосов
/ 03 февраля 2011

Просто настройте приложение 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')

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

0 голосов
/ 19 декабря 2016

У меня была в основном та же проблема, что и в оригинальном плакате, и ее легко исправить, переопределив классы 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

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

0 голосов
/ 29 октября 2014

Модификация ответа @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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...