我有两个型号。一个是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)
假设只有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)
在我用完游泳池之前它一直很好用(所有这些游戏都分配了4个用户)。我应该如何从Django管理员处理这个?理想情况下,我想向用户显示一些错误消息,以便他可以创建更多池。
我宁愿不将池分配代码移动到表单的clean()
方法,因为可能还会从不同的界面创建用户,而不是管理GUI。
有什么想法吗?
非常感谢!
答案 0 :(得分: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.')
这将从管理员自动调用(请参阅ModelForm
validation上的文档)。或者 - 如果您没有清除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(..)
您可以在self.full_clean()
内调用save()
进行验证,但此版本似乎更直接(并且效率更高)。