Функция вызова Django при добавлении объекта - PullRequest
0 голосов
/ 02 июня 2010

Хей, у меня простая модель

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 .

Как бы я это сделал?

EDIT

Хотелось бы что-нибудь подобное?

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

Ответы [ 4 ]

4 голосов
/ 02 июня 2010

Лучший способ заставить что-то произойти, когда модель сохраняется, чтобы использовать сигнал. Документация 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)

В свете требований, добавленных вашим комментарием, вы вернулись к обновлению поля в модели производителя при каждом сохранении автомобиля. Я все еще рекомендовал бы использовать метод 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()

Тогда вы бы подключили его к сигналам post_save и post_delete модели Car.

post_save.connect(update_car_count, sender=Car)
post_delete.connect(update_car_count, sender=Car)
2 голосов
/ 02 июня 2010

Правильный способ показать базе данных, сколько автомобилей имеет производитель, - позволить базе данных рассчитать ее в представлении с использованием агрегатов.

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

Базы данных очень эффективны для такого рода вещей, и вы можете упорядочить результаты, как показано выше.

2 голосов
/ 02 июня 2010

Я немного запутался.

.. когда автомобиль добавляется к производителю ..

В коде, показанном в вашем вопросе, я полагаю, вы сохраняете машину у какого-то производителя, например,

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

Тогда методу сохранения класса Car потребуется обновить car_count производителя (см. Переопределение предопределенных методов модели для получения более подробной информации).

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 изучить сигналов .

P.S. Вы также можете добавить метод в класс «Производитель», но я думаю, вы хотите, чтобы этот атрибут находился в базе данных.

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

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

    car_count = property(_car_count)

...
0 голосов
/ 02 июня 2010

Переопределение в ответе 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()

Что не проверено, но должно работать.

Конечно, лучший способ - это использовать решение Джоша, так как оно идет «с зерном» Джанго.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...