Если есть две модели:
class Invoice(models.Model):
class Meta:
ordering = ('-date_added', )
number = models.CharField(max_length=10,)
comments = models.TextField(blank=True, help_text="Notes about this invoice." )
total = models.DecimalField(max_digits=9, decimal_places=2, default="0" )
date_added = models.DateTimeField(_('date added'), auto_now_add=True)
date_modified = models.DateTimeField(_('date modified'), auto_now=True)
def __unicode__(self):
return "%s: total %s" % (self.number, self.total)
class Part(models.Model):
for_invoice = models.ForeignKey(Invoice)
description = models.CharField(max_length=200, blank=True, help_text=_("Briefly describe the part.") )
supplier = models.CharField(max_length=100, blank=True, help_text=_("Supplier Name.") )
supplier_number = models.CharField(max_length=100, blank=False, help_text=_("Supplier's order number.") )
qty = models.DecimalField(max_digits=3, decimal_places=0, blank=False, null=False, help_text=_("How many are needed?") )
cost = models.DecimalField(max_digits=7, decimal_places=2, blank=True, null=True, help_text=_("Price paid per unit") )
line_total = models.DecimalField(max_digits=9, decimal_places=2, default="0")
date_added = models.DateTimeField(auto_now_add=True)
date_modified = models.DateTimeField(auto_now=True)
def __unicode__(self):
return "%s: total %s" % (self.for_invoice, self.line_total)
Первый вариант, который я вижу, - это реализовать «line_total» или «total» в качестве вычисляемого поля модели. Но если вы сделаете это, вы никогда не сможете отсортировать список изменений по «line_total» или «total», и пользователи хотят иметь возможность это делать. Поэтому я сделал их сохраненным полем на модели.
Читая документы Django 1.10, я вижу 4 места, где можно определить код для вычисления и обновления полей «total» и «line_total»:
- ModelAdmin.save_model(запрос, объект, форма, изменение) и ModelAdmin.save_formset(запрос, форма, набор форм, изменение)
- ModelAdmin.save_related(запрос, форма, наборы форм, изменение)
- model.save(я, *args, **kwargs))
- Сохранить сигнал
Мне кажется, что сигнал сохранения слишком низкоуровневый — привязан к одному событию сохранения модели, и у него никогда не будет доступа к запросу или сессии. Значит, было бы "раздражающе" пытаться собрать все записи "Part"?
Точно так же кажется, что метод model.save также будет слишком гранулированным. Было бы «удобно», если бы я мог использовать метод Invoice.save, так как он имеет легкий доступ ко всем связанным частям через Invoice.part_set.all(), цикл по этому набору запросов был бы простым способом обновить line_total, затем основной общий. Но опять же, будут ли в этот момент сохранены все новые/измененные записи Part? И у него не будет доступа к HttpRequest.
Я думаю, то же самое относится и к save_model администратора. Тем не менее, у меня смутное воспоминание о том, что можно сначала сохранить связанные части. Я перечисляю части, используя встроенную строку на странице добавления/редактирования счета-фактуры в Admin.
Я только что добавил в ModelAdmin.save_related! Я забыл об этом. Поскольку на этом этапе будет сохранен основной счет, может быть, это лучшее место для обновления всех записей о деталях, а затем обновления родительской суммы?
Заранее спасибо!