1👍
✅
You can use KeyTextTransform and aggregate function together to achieve this.
from django.db.models import Sum, IntegerField
from django.db.models.fields.json import KeyTextTransform
from django.db.models.functions import Cast
# Sum of total_price from all Foo instances
total_price_sum = Foo.objects.annotate(
total_price_int=KeyTextTransform('total_price', 'cart')
).aggregate(
total=Sum(Cast('total_price_int', output_field=IntegerField()))
)
print(total_price_sum['total'])
Uses KeyTextTransform to extract the value of the ‘total_price’ key from the ‘cart’ JSON field.
Then, aggregate the sum of the extracted values using the Sum function and the Cast function to convert the values to integers.
0👍
I created a custom DB function for jsonb_extract_path_text(...)
from django.db.models import Aggregate
class JSONBExtractPathText(Aggregate):
function = 'jsonb_extract_path_text'
template = None
def get_template(self):
# https://stackoverflow.com/a/38985104/8283848
paths = str(self.extra['path'])[1:-1]
return f"%(function)s(%(jsonb_field)s, {paths})"
def as_sql(self, *args, **kwargs):
kwargs["template"] = self.get_template()
return super().as_sql(*args, **kwargs)
and used as
from django.db.models.functions import Cast
from django.db.models import Sum, IntegerField
from .models import Foo
result = Foo.objects.aggregate(
total_price=Sum(
Cast(
JSONBExtractPathText(
path=["nested", "price"],
jsonb_field="cart"),
output_field=IntegerField(),
)
)
)
print(result)
# {'total_price': 100}
👤JPG
- [Answered ]-Incorrect value – python to model in Django
- [Answered ]-Error from installing Django using pip on mac
- [Answered ]-I'm having trouble deciding between using a foreign key, many-to-many field, or choicefield
- [Answered ]-Session issue with django+apache+mod_wsgi
Source:stackexchange.com