Django: удалить десятичный префикс из аннотированного поля queryset при запросе значений - PullRequest
0 голосов
/ 17 января 2020

Короче говоря, у меня есть этот набор запросов:

monthly_revenue = list(Booking.objects.annotate(month=Month('created_at'))
                           .values('month')
                           .annotate(total=Sum('price'))
                           .order_by('month'))

это то, что он возвращает:

[{'month': 11, 'total': Decimal('4550.00')}]

результат собирается сценарию js, чтобы показать график, и мне нужно удалить префикс Decimal(). Любая помощь или подсказка приветствуется.

Ответы [ 4 ]

2 голосов
/ 17 января 2020

Если вы просто хотите удалить префикс «Десятичный», вы можете просто указать конкретное c выходное поле в аннотации:

monthly_revenue = list(Booking.objects.annotate(month=Month('created_at'))
                           .values('month')
                           .annotate(total=Sum('price', output_field=FloatField()))
                           .order_by('month'))
1 голос
/ 17 января 2020

Поскольку вы используете Django, вы можете использовать DjangoJSONEncoder следующим образом:

from django.core.serializers.json import DjangoJSONEncoder

my_dict = [{'month': 11, 'total': Decimal('4550.00')}]
json_result = json.dumps(my_dict, cls=DjangoJSONEncoder)

Но имейте в виду, что DjangoJSONEncoder преобразует десятичную в строки, поэтому результат будет:

[{"month": 11, "total": "4550.00"}]

Если вы перейдете к DjangoJSONEncoder исходному коду, вы найдете это:

elif isinstance(o, (decimal.Decimal, uuid.UUID, Promise)):
    return str(o)
1 голос
/ 17 января 2020

вы можете преобразовать его в тип float, например:

monthly_revenue = list(Booking.objects.annotate(month=Month('created_at'))
                       .values('month')
                       .annotate(total=float(Sum('price')))
                       .order_by('month'))
0 голосов
/ 17 января 2020

Я наконец нашел два решения, которые работали для меня: Благодаря ответу @ Ramy я переопределил DjangoJSONEncoder, чтобы поддержать преобразование десятичного числа в число с плавающей точкой:

import decimal
import uuid
from django.utils.functional import Promise
from django.core.serializers.json import DjangoJSONEncoder

class JsonDecimalToFloatEncoder(DjangoJSONEncoder):
def default(self, o):
    if isinstance(o, (decimal.Decimal, uuid.UUID, Promise)):
        return float(o)
    return super().default(o)

и я использовал его, как он упоминал:

monthly_revenue = list(Booking.objects.annotate(month=Month('created_at'))
                               .values('month')
                               .annotate(total=Sum('price'))
                               .order_by('month'))
json_result = json.dumps(monthly_revenue,cls=ExtendedEncoder)
json_result
'[{"month": 11, "total": 4550.0}]'

это решение требует больше работы на стороне сервера, поэтому я выбрал второе решение @ rossi , которое делает больше работать с базой данных, а не с сервером, и это то, что предлагает документация django.

from django.db.models import FloatField
from django.db.models.functions import Cast

list(Booking.objects.annotate(month=Month('created_at'))
                              .values('month')                                
                              .annotate(total_as_f=Cast('total', 
                               output_field=FloatField()))
                              .order_by('month'))

[{'month': 11, 'total': Decimal('4550.00'), 'total_as_f': 4550.0}]

надеюсь, что это поможет любому в будущем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...