限制要创建的模型实例的数量 - django

时间:2010-01-26 09:17:10

标签: django django-models django-admin

我有模型,我只想创建一个实例,不应再允许实例。

这可能吗?我有一种感觉,我已经在某个地方看到过这种情况,但不幸的是我无法找到它。

编辑: 我需要这个用于一个简单的简单CMS。我有一个FrontPage和Page类继承的抽象类。我只想创建一个首页对象。

FrontPage对象和Page对象之间的区别在于它们应该具有稍​​微不同的字段和模板,并且如上所述,仅创建一个FrontPage。

6 个答案:

答案 0 :(得分:30)

我想自己做类似的事情,发现Django的模型验证提供了一个方便的执行钩子:

from django.db import models
from django.core.exceptions import ValidationError

def validate_only_one_instance(obj):
    model = obj.__class__
    if (model.objects.count() > 0 and
            obj.id != model.objects.get().id):
        raise ValidationError("Can only create 1 %s instance" % model.__name__)

class Example(models.Model):

    def clean(self):
        validate_only_one_instance(self)

这不仅阻止了新实例的创建,而且Django管理员UI实际上会报告创建失败,原因是“只能创建1个示例实例”(而早期的返回方法)在文档中没有说明保存为什么不起作用。)

答案 1 :(得分:23)

如果您只是想阻止使用管理界面的用户创建额外的模型对象,您可以修改模型的ModelAdmin类的“has_add_permission”方法:

# admin.py
from django.contrib import admin
from example.models import Example

class ExampleAdmin(admin.ModelAdmin):
  def has_add_permission(self, request):
    num_objects = self.model.objects.count()
    if num_objects >= 1:
      return False
    else:
      return True

admin.site.register(Example, ExampleAdmin)

这将删除管理界面中的“添加”按钮,防止用户甚至尝试创建超过指定数量(在本例中为1)。当然,编程补充仍然是可能的。

答案 2 :(得分:3)

您可以执行以下操作:from the Django docs

class ModelWithOnlyOneInstance(models.Model):
    ... fields ...

    def save(self, *args, **kwargs):
      if ModelWithOnlyOneInstance.objects.count() > 1:
        return

      super(ModelWithOnlyOneInstance, self).save(*args, **kwargs)

答案 3 :(得分:2)

@ncoghlan你的解决方案工作正常,但用户不太友好:用户可以访问创建表单并认为他/她可以使用它,即使他/她永远无法保存它。 / p>

实际上可以将它与Brendan的解决方案结合起来,这将隐藏“添加”按钮。使用Mixins轻松重复使用:

# models.py
from django.db import models
from django.core.exceptions import ValidationError

class SingleInstanceMixin(object):
    """Makes sure that no more than one instance of a given model is created."""

    def clean(self):
        model = self.__class__
        if (model.objects.count() > 0 and self.id != model.objects.get().id):
            raise ValidationError("Can only create 1 %s instance" % model.__name__)
        super(SingleInstanceMixin, self).clean()

class Example(SingleInstanceMixin, models.Model):
    pass


# admin.py
from django.contrib import admin
from example.models import Example

class SingleInstanceAdminMixin(object):
    """Hides the "Add" button when there is already an instance."""
    def has_add_permission(self, request):
        num_objects = self.model.objects.count()
        if num_objects >= 1:
            return False
        return super(SingleInstanceAdminMixin, self).has_add_permission(request)

class ExampleAdmin(SingleInstanceAdminMixin, admin.ModelAdmin):
     model = Example

答案 4 :(得分:0)

我会覆盖默认管理器上的create()方法,但如上所述,这不能保证多线程环境中的任何内容。

答案 5 :(得分:0)

如果您只想要模型的一个实例,也许“有一个应用程序可供使用!”

您可以检查django-solo witch是您需要的完整解决方案。

这是链接-> https://github.com/lazybird/django-solo

它带有一个用于单例模型的类和一个用于管理单例模型的类,女巫没有在模型名称的末尾添加s,排除了中间屏幕女巫列出了所有对象,还删除了“添加”按钮和“保存并添加另一个”按钮。

它还附带了其他一些蓬松而有用的内容,例如直接将单例导入模板中等等。