Пользовательское сохранение модели Django с проблемой ManyToManyField - PullRequest
2 голосов
/ 06 июня 2009

Я знаю, что этот вопрос был опубликован несколько раз, но я все еще не смог найти однозначного ответа на эту проблему Итак, я иду:

class Invoice(models.Model):
    program = models.ForeignKey(Program)
    customer = models.ForeignKey(Customer, related_name='invoices')
    participants = models.ManyToManyField(Participant, related_name='participants_set')
    subtotal = models.DecimalField(max_digits=10, decimal_places=2, default='0.00', blank=True, null=False)
    pst = models.DecimalField("PST", max_digits=10, decimal_places=2, default='0.00', blank=True, null=False)
    gst = models.DecimalField("GST", max_digits=10, decimal_places=2, default='0.00', blank=True, null=False)
    total = models.DecimalField(max_digits=10, decimal_places=2, default='0.00', blank=True, null=False)

    def save(self, **kwargs):
        super(Invoice, self).save(**kwargs)
        items = self.participants.count()
        subtotal = Decimal(self.program.fee) * items
        pst = self.program.is_pst and Decimal(PST)*subtotal or Decimal('0.00')
        gst = self.program.is_gst and Decimal(GST)*subtotal or Decimal('0.00')
        total = (subtotal + pst) + gst
        self.subtotal = subtotal
        self.pst = pst
        self.gst = gst
        self.total = total
        super(Invoice, self).save(**kwargs)

Все работает нормально, кроме self.participants.count () не работает. Любая идея, в чем может быть проблема. Любая помощь высоко ценится.

Ответы [ 4 ]

5 голосов
/ 08 декабря 2009
self.participants.all().count()
0 голосов
/ 08 июня 2009

Я думаю, что происходит, потому что вы пытаетесь подсчитать количество участников во время сохранения, запрос может не найти все. Если вы зависите от этого числа во время создания базы данных, я не думаю, что таблица «многие ко многим» будет синхронизирована правильно, потому что Invoice еще не присвоен ID.

И наоборот, другие участники не могут быть сохранены в базе данных. В любом случае, в зависимости от этого числа во время сохранения не будет работать, независимо от использования сигналов. Я бы порекомендовал иметь отдельный метод, который делает это вычисление. Он чище, повышает эффективность сохранения и позволяет вызывать его без сохранения.

0 голосов
/ 13 июля 2009

У меня была похожая проблема. У меня была модель, которая поддерживала теги стиля del.icio.us. Функция сохранения будет анализировать список тегов (например, «python django web») и преобразовывать их в отдельные экземпляры объектов тегов, вызывая вспомогательную функцию update_tags () (см. Упрощенный пример ниже). Однако ManyToManyField не будет отражать изменения, когда я редактировал объект в интерфейсе администратора.

class Article(models.Model):
    tag_string = models.CharField(max_length=255, null=True, blank=True) #del.icio.us style tags, like: django python software
    tags =  models.ManyToManyField(Tag, blank=True)

    def save(self, force_insert=False, force_update=False):
        super(Article, self).save(force_insert, force_update)

        self.update_tags() #The result of this function didn't seem to be saved in the ManyToManyField

Оказывается, интерфейс администратора переопределял изменения в ManyToManyField. Решением было просто удалить ManyToManyField из admin.ModelAdmin:

class ArticleAdmin(admin.ModelAdmin):
    exclude = ['tags']
0 голосов
/ 07 июня 2009

Вместо переопределения метода сохранения, я бы рекомендовал использовать сигнал предварительного сохранения . Помимо того, что ваш код немного чище, он помогает избежать странных проблем, подобных этим:)

...