Django-polymorphic Сумма агрегатов Цена

Мне нужен чистый способ суммировать цену всех продуктов в наборе запросов при использовании django-polymorphic.

Установите зависимости:

pip install django-polymorphic

Создайте приложение:

manage.py startapp content

путь: content/models.py

from django.db import models
from polymorphic.models import PolymorphicModel
from polymorphic.managers import PolymorphicManager
from django.utils.text import slugify
from django.contrib.auth.models import AbstractUser


class User(AbstractUser):
    pass

class Content(PolymorphicModel):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='content')
    title = models.CharField(max_length=100)
    slug = models.SlugField(max_length=100)

    objects = PolymorphicManager()

    class Meta:
        unique_together = ('user', 'slug')

    def __str__(self):
        return str(self.title)

    def save(self, *args, **kwargs):
        self.slug = slugify(self.title)
        super().save(*args, **kwargs)

class Post(Content):
    pass

class Note(Content):
    pass

class ProductA(Content):
    price = models.DecimalField(max_digits=6, decimal_places=2, null=True)

class ProductB(Content):
    price = models.DecimalField(max_digits=6, decimal_places=2, null=True)

путь: project/settings.py

INSTALLED_APPS = [
    ...
    'content.apps.ContentConfig' # add this
]

AUTH_USER_MODEL = 'content.user'

Выполнено:

manage.py makemigrations
manage.py migrate

В интерактивной оболочке:

u, _ = User.objects.get_or_create(username='user')
post = Post.objects.create(user=u, title='First Post')
note = Note.objects.create(user=u, title='First Note')
prod_a = ProductA.objects.create(user=u, title='First Product A', price=12.99)
prod_b = ProductB.objects.create(user=u, title='First Product B', price=18.99)

Мне нужен чистый способ суммирования цен всех продуктов в наборе запросов.

Пример:

qs = Content.objects.instance_of(ProductA, ProductB)

Возврат:

<PolymorphicQuerySet [<ProductA: First Product A>, <ProductB: First Product B>]>

Поскольку продукт A и B оба имеют price, я подумал, что могу сделать:

qs.aggregate(total=Sum('price'))

но это приводит к ошибке:

django.core.exceptions.FieldError: Cannot resolve keyword 'price' into field.
  Choices are: id, note, polymorphic_ctype, polymorphic_ctype_id, post,
  producta, productb, slug, title, user, user_id

Я попробовал следующее:

qs.aggregate(total=Sum(Coalesce('producta__price', 'productb__price')))

что дает правильный ответ (12,99 + 18,99 = 31,98)

{'total': Decimal('31.9800000000000')}

but I have never used Coalesce before, don't know what it's doing, or if it's reliable as a solution in this case. Documentation says "returns the first non-null value" which sounds like it would return the first price only, but it seems to return all values that are not null? If a product will always have a price, would Coalesce be a good choice for finding the total price value of products?

I wondered about using Q() but not sure how I would do that in this case.

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