在Django Admin上使用自定义save()方法保存模型后返回错误消息

Ign*_*ona 5 django django-admin

我有两个型号.一个是Subscriber在节省时间我根据已经分配给该池的订户数量来分配池:

class Subscriber(models.Model):
    pool = models.ForeignKey(Pool)
    interface = models.CharField(max_length=30)


class Pool(models.Model):
    name = models.CharField(max_length=50)
Run Code Online (Sandbox Code Playgroud)

假设只有4个Subscribers可以分配给一个池.这就是为什么我要覆盖Subscriber的save()方法:

def save(self, *args, **kwargs):
    if not self.pk:
        #Look for a free Pool among the available ones
        for pool in Pool.objects.all():
            if pool.subscriber_set.count() < 4:
                self.pool = pool
                print "Assigned pool: %s" % pool.name
                super(Subscriber, self).save(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

它运行良好,直到我用完池(所有这些都分配了4个用户).我应该如何从Django管理员处理这个?理想情况下,我想向用户显示一些错误消息,以便他可以创建更多池.

我宁愿不将池分配代码移动到窗体的clean()方法,因为可能用户也将从不同的界面创建,而不是管理GUI.

有任何想法吗?

非常感谢!

Kev*_*nry 6

我会建议在这两个验证clean()save().前者将在管理员中为您提供一个很好的错误消息和工作流,而后者将确保save()自己提供错误消息,无论您是如何创建实例.

首先验证:

class Subscriber(models.Model):

    def clean(self)
        if not self.pk:
            if not Pool.objects.annotate(num_subscribers=Count('subscriber'))
                               .filter(num_subscribers__lt=4)
                               .exists():
                raise ValidationError('The pools are all full.')
Run Code Online (Sandbox Code Playgroud)

这将从管理员自动调用(请参阅有关ModelForm验证的文档).或者 - 如果您没有清除ModelForm验证之外的东西- 您可以使用表单的clean()方法提供此逻辑.

然后在save()方法中做同样的事情.

    def save(self, *args, **kwargs):
        if not self.pk:
            try:
                self.pool = Pool.objects.annotate(num_subscribers=Count('subscriber'))
                                        .filter(num_subscribers__lt=4)[0]
                super(Subscriber, self).save(*args, **kwargs)
            except IndexError:
                raise ValidationError(..)
Run Code Online (Sandbox Code Playgroud)

你可以调用self.full_clean()内部save()来进行验证,但是这个版本似乎更简单(并且肯定更有效).