添加对象时的Django调用函数

时间:2010-06-01 21:57:03

标签: django

Hay,我有一个简单的模型

class Manufacturer(models.Model):
    name = models.CharField()
    car_count = models.IntegerField()

class Car(models.Model):
    maker = ForeignKey(Manufacturer)

我想在将汽车添加到制造商时更新car_count字段,我知道我可以只计算Manufacturer.car_set()来获取值,但我希望该值存储在该car_count字段中

我该怎么做?

修改

这样的事情会起作用吗?

    def save(self):
        if self.id:
            car_count = self.car_set.count()
            self.save()

4 个答案:

答案 0 :(得分:4)

当模型被保存以使用信号时,最好的方法是让事情发生。 Django的文档很好地描述了信号是什么以及如何使用它们:http://docs.djangoproject.com/en/dev/topics/signals/

我不确定为什么你需要让它成为模型中的一个字段。数据库非常擅长计算行数,因此您可以添加一个模型方法来计算使用非常快速的COUNT()查询的汽车。

class Manufacturer(models.Model):
    name = models.CharField()

    def car_count(self):
        return Car.objects.filter(maker=self).count()

class Car(models.Model):
    maker = ForeignKey(Manufacturer)

根据评论添加的要求,只要保存了Car,您就会返回更新Manufacturer模型上的字段。我仍然建议使用count()方法来确保car_count字段是准确的。所以你的信号处理程序看起来像这样:

def update_car_count(sender, **kwargs):
    instance = kwargs['instance']
    manufacturer = instance.maker
    manufacturer.car_count = Car.objects.filter(maker=self).count()
    manufacturer.save()

然后你将它连接到Car模型的post_save和post_delete信号。

post_save.connect(update_car_count, sender=Car)
post_delete.connect(update_car_count, sender=Car)

答案 1 :(得分:2)

我有点困惑。

  

..当汽车被添加到制造商时..

在你问题中显示的代码中,我猜,你可以用一些制造商保存汽车,例如

car.maker = Manufacturer.objects.get(name='BMW')
car.save()

然后,Car类的save方法需要更新制造商的car_count(有关详细信息,请参阅Overriding predefined model methods)。

def save(self, *args, **kwargs):
    if self.id:
        self.maker.car_count = len(self.maker.car_set.all())
    super(Car, self).save(*args, **kwargs)

由于这不是最优雅的代码,我建议@Josh Wright调查signals

P.S。您也可以在Manufacturer类上添加一个方法,但我想,您希望此属性存在于数据库中。

class Manufacturer(models.Model):
    name = models.CharField()

    def _car_count(self):
        return len(self.car_set.all())

    car_count = property(_car_count)

...

答案 2 :(得分:2)

让数据库显示制造商拥有的汽车数量的正确方法是让数据库使用聚合在视图中计算它。

from django.db.models import Count
Manufacturer.objects.all().annotate(car_count=Count(car)).order_by('car_count')

数据库在这种情况下非常有效,您可以按照上面的结果订购。

答案 3 :(得分:0)

MYYN的答案中的覆盖不起作用,因为Car.id将不会被设置(并且可能不包括在制造商的car_set中),直到它被保存。相反,我会做类似的事情:

def save(self, *args, **kwargs):
    super(Car, self).save(*args, **kwargs)
    self.maker.car_count = len(self.maker.car_set.all())
    self.maker.save()

哪个未经测试,但应该有用。

当然,最好的方法是使用Josh的解决方案,因为那将是'与Django一样'。