I’m trying to get specific fields from my database using the object.values() attribute, as such:

stocks = Stock.objects.values("ticker", "stock", "exchange__exchange_code", "earnings_yield", "roic")

The reason I’m not using Stock.objects.filter()... is because I only need a subset of the fields, and as far as I know, values() is the way to go.

stocks[0] returns this:

{
 'ticker': 'ATRLJ-B', 
 'stock': 'Atrium Ljungberg AB (publ)', 
 'exchange__exchange_code': 'ST', 
 'earnings_yield': Decimal('0.0250'), 'roic': Decimal('0.0200')
}

How do I get earnings_yield and roic as regular floats? E.g, proper JSON formatted

I tried

clean = json.dumps(list(stocks), cls=DjangoJSONEncoder)
stocks = json.loads(clean)

But that returns the decimals as strings, not decimals


Answer

I think you can do it with ExpressionWrapper, use FloatField as output field and store it to another field name.

from django.db.models import FloatField, F, ExpressionWrapper

Stock.objects.annotate(
  earnings_yield_float=ExpressionWrapper(
    F('earnings_yield'),
    output_field=FloatField()
  ),
  roic_float=ExpressionWrapper(
    F('roic'),
    output_field=FloatField()
  )
).values(
    'ticker',
    'stock',
    'exchange__exchange_code',
    'earnings_yield_float',
    'roic_float'
)

But, bassed on your case, I’ll recomend you to use https://www.django-rest-framework.org instead. By using this, your Stock data will be converted as JSON format when you call serializer.data (like below example):

For example in your serializers.py

from rest_framework import serializers
from yourapp.models import Stock


class StockSerializer(serializers.ModelSerializer):

    class Meta:
        model = Stock
        fields = ('ticker', 'stock', 'exchange__exchange_code', 
                  'earnings_yield', 'roic')

Then in your views.py:

from rest_framework import generics
from rest_framework.response import Response
from yourapp.models import Stock


class StockView(generics.ListAPIView):
    queryset = Stock.objects.all()

    def get_queryset(self):
        return self.queryset.filter(...)

    def list(self, request):
        queryset = self.get_queryset()
        serializer = StockSerializer(queryset, many=True)
        return Response(serializer.data)

Meanwhile, StockSerializer(queryset, many=True).data will return OrderDict, but for a single object it will return as JSON output.

The other way, if you want to dealing with exact JSON output at all, you can use default rest_framework.renderers.JSONRenderer.

from rest_framework.renderers import JSONRenderer
from yourapp.serializers import StockSerializer
from yourapp.models import Stock

queryset = Stock.objects.all()
serializer = StockSerializer(queryset, many=True)
data = JSONRenderer().render(serializer.data)  # b'[{"id":1, "ticker": ...}]

# the to proces that data you can use the json module
import json
json.loads(data)  # [{'id': 1, 'ticker': ...}]
172 2 2 0