Django模型:只允许模型中的一个条目?

时间:2011-02-03 15:37:31

标签: 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_emailintro_text等。

我是否可以阻止管理员用户在此处添加新记录,而不会阻止他们编辑现有记录

我想我可以通过为此模型编写自定义管理模板来实现此目的,但我想知道是否有更简洁的方法来配置它。

我可以使用class以外的其他内容吗?

谢谢!

8 个答案:

答案 0 :(得分:16)

请参阅this question on "keep[ing] settings in database",答案似乎是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应用程序,因为它完全符合您的要求 - 提供用户可编辑的设置 - 而不会让您做任何额外的,不必要的工作。

答案 1 :(得分:10)

我认为最简单的方法是使用ModelAdmin的has_add_permissions函数:

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。

答案 2 :(得分:3)

尝试django-constance。 以下是一些有用的链接:

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

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

答案 3 :(得分:2)

只需设置一个GlobalSettings应用或带有键和值字段的内容即可。

您可以轻松阻止管理员用户更改值,方法是不授予他们编辑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')

有这样的应用程序,但我更喜欢看它们并自己编写。

答案 4 :(得分:2)

您可以通过在管理类上覆盖此方法来阻止用户添加/删除对象:

ModelAdmin.has_add_permission(self, request)

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

答案 5 :(得分:2)

我从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和电话一样狡猾。 AdminOptions.get_option(opt_name)

然后,您可以将自定义设置加载到运行时,使settings.py模块保持独立,但相等。写这个的好地方是__init__.py文件。

答案 6 :(得分:0)

修改@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

答案 7 :(得分:0)

我的原始海报描述的问题基本相同,并且可以通过覆盖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

这并不会阻止用户发布编辑数据的表单,但会阻止管理站点中发生的事情。根据您是否认为满足您的需求,您可以使用最少的编码来删除和添加记录。