Подсчет суммы объектов модели в сериализаторах django

В моем приложении у каждого пользователя есть свой кошелек, в котором он может сохранять свои ежедневные расходы.

Как я могу получить сумму денег для каждого экземпляра кошелька, в котором сохранено много расходов?

Я пробовал serializers.SerializerMethodField()

from django.db.models import Sum
from django.db.models import Q

class WalletInstanceSerializer(serializers.ModelSerializer):
    owner = serializers.ReadOnlyField(source='owner.id')
    entry = BudgetEntrySerializer(many=True, read_only=True)
    expense_sum = serializers.SerializerMethodField()

    class Meta:
        model = WalletInstance
        fields = '__all__'

    def get_expense_sum(self, obj):

        return WalletInstance.objects.filter(Q(id=obj.id)|Q(entry__entry_type='income')).aggregate(Sum('entry__amount'))['entry__amount__sum']

И это дает мне данные в правильном формате, но сумма неправильная, например

[
    {
        "id": "d458196e-49f1-42db-8bc2-ee1dba438953",
        "owner": 1,
        "entry": [
            {
                "id": 3,
                "owner": 1,
                "title": "dsfdsf",
                "amount": 7,
                "description": "sdfdsf",
                "entry_type": "income",
                "date_added": "2022-08-13",
                "entry_category": {
                    "id": 2,
                    "name": "Transport"
                }
            },
            {
                "id": 4,
                "owner": 1,
                "title": "fesfvsdfgvbtdg",
                "amount": 12,
                "description": "efesf",
                "entry_type": "income",
                "date_added": "2022-08-13",
                "entry_category": {
                    "id": 2,
                    "name": "Transport"
                }
            }
        ],
        "viewable": [
            "admin@gmail.com"
        ],
        "expense_sum": 83,
        "name": "dsdsds",
        "date_added": "2022-08-13"
    }
]

Сумма_расходов равна 83, но поля суммы равны 7 и 12, так что это равно 19

Как я могу получить правильное число?

Модели

class BudgetEntry(models.Model):
    STATE= [
        ('income','income'),
        ('expenses','expenses'),
    ]
    owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='owner_of_entry', on_delete=models.CASCADE)
    title = models.CharField(max_length=20)
    amount = models.IntegerField()
    description = models.CharField(max_length=60, null=True)
    entry_type = models.CharField(max_length=15, choices=STATE, null=True)
    entry_category = models.ForeignKey(Category, null=True, blank=True, related_name='category_of_entry', on_delete=models.SET_NULL)
    date_added = models.DateField(auto_now_add=True)



class WalletInstance(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True)
    name = models.CharField(max_length=30, null=True)
    owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='owner', on_delete=models.CASCADE)
    viewable = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='can_view', blank=True)
    entry = models.ManyToManyField(BudgetEntry, related_name='BudgetEntry', blank=True)
    date_added = models.DateField(auto_now_add=True)

Я думаю, что ORM запрос для BudgetEntry неправильный. Он должен выглядеть следующим образом:

def get_expense_sum(self, obj):
    return obj.entry.filter(entry_type='income').aggregate(Sum('entry__amount'))['entry__amount__sum']

Я разобрался с этим. Сначала я создал @property в моей базе данных для получения суммы расходов, но это было не очень полезно, если бы я захотел посчитать доходы, поэтому я передал значение arg в функцию, где значение может быть расход/доход

class WalletInstance(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True)
    name = models.CharField(max_length=30, null=True)
    owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='owner', on_delete=models.CASCADE)
    viewable = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='can_view', blank=True)
    entry = models.ManyToManyField(BudgetEntry, related_name='BudgetEntry', blank=True)
    date_added = models.DateField(auto_now_add=True)

    def total_amount(self, value):
        queryset = self.entry.filter(entry_type=value).aggregate(
            total_amount=models.Sum('amount'))
        return queryset["total_amount"]

Теперь я вызываю эту функцию в своем сериализаторе вместо того, чтобы считать там

class WalletInstanceSerializer(serializers.ModelSerializer):
    owner = serializers.ReadOnlyField(source='owner.id')
    entry = BudgetEntrySerializer(many=True, read_only=True)
    viewable = serializers.SlugRelatedField(many=True, queryset=get_user_model().objects.all(), slug_field='email')
    expense_sum = serializers.SerializerMethodField()

    class Meta:
        model = WalletInstance
        fields = '__all__'

    def get_expense_sum(self, obj):
        wallet_obj = WalletInstance.objects.get(id=obj.id)
        return wallet_obj.total_amount('expenses')

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