Агрегатная сумма Django по полю дочерней модели

Рассмотрите следующие модели:

from django.db import models
from django.db.models import Sum
from decimal import *

class Supply(models.Model):
    """Addition of new batches to stock"""
    bottles_number = models.PositiveSmallIntegerField(
    bottles_remaining = models.DecimalField(max_digits=4, decimal_places=1, default=0.0)

    def remain(self, *args, **kwargs):
        used = Pick.objects.filter(supply=self).aggregate(
                                   total=Sum(Pick.n_bottles))[bottles_used__sum]
        left = self.bottles_number - used
        return left

    def save(self, *args, **kwargs):
        self.bottles_remaining = self.remain()
        super(Supply, self).save(*args, **kwargs)

class Pick(models.Model):
    """ Removals from specific stock batch """
    supply = models.ForeignKey(Supply, on_delete = models.CASCADE)
    n_bottles = models.DecimalField(max_digits=4, decimal_places=1)

Каждый раз, когда товар (в данном случае бутылки) используется, мне нужно обновить поле "bottles_remaining", чтобы показать текущее количество на складе. Я знаю, что лучшая практика обычно заключается в том, чтобы не хранить в базе данных значения, которые могут быть вычислены на лету, но мне нужно сделать это, чтобы иметь данные, доступные для использования за пределами Django.

Это часть системы управления запасами, изначально построенной на PHP через Xataface. Не будучи опытным программистом, я смог сделать большую часть этого с помощью гугла, но теперь я полностью застрял на этой ключевой функции. Функция remain(), вероятно, представляет собой полный беспорядок. Любые подсказки о том, как выполнить этот расчет и извлечь значение, будут очень признательны.

Не уверен, что вы на самом деле хотите решить и в чем именно заключается проблема.

Возможными решениями являются

  1. Use SQL View
CREATE VIEW bottles_extended AS
SELECT id, total_number, used, (total_number - used) as remaining
FROM bottles;

После этого вы можете просто получить данные в виде select total_number, used, remaining from bottles_extended на стороне PHP

  1. Add (total_number - used) as remaining column directly in PHP SQL query

  2. Current Django solution to update field automatically on save looks not perfect but also should be working solution (in addition you may add serializers and set serializer's remaining field as read only. This will prevent to change value by user manually)

Вернуться на верх