class Transactions(models.Model):
id = models.CharField(max_length=100, primary_key=True)
owner = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
date = models.DateField()
watch = models.CharField(max_length=100)
purchase_price = models.IntegerField()
sale_price = models.IntegerField()
My Transactions model has a date field, purchase price, and sale_price.
@api_view(['GET'])
@permission_classes([IsAuthenticatedOrReadOnly])
def profit_chart(request):
current_year = datetime.now().year
queryset = Transactions.objects.filter(date__year=current_year).values(month=ExtractMonth('date'),
year=ExtractYear('date')).annotate(
profit=Sum(F('sale_price')) - Sum(F('purchase_price'))).order_by('month')
serializer = ProfitChartSerializer(queryset, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
My view sorts transactions by the current year and month and then calculates the profit for that month.
class ProfitChartSerializer(serializers.ModelSerializer):
year = serializers.IntegerField()
month = serializers.IntegerField()
profit = serializers.IntegerField()
class Meta:
model = Transactions
fields = ['year', 'month', 'profit']
The response I get from DRF is below.
[
{
"year": 2024,
"month": 8,
"profit": 5000
}
]
The question I am trying to figure out is how I can manipulate the above response to look like below.
[
year: 2024
data: {
month: 8
profit: 5000
}
]
I don't think it makes much sense. Indeed, you filter by year:
queryset = Transactions.objects.filter(date__year=current_year)
so the year of all returned records will be the same.
Here you can however customize the serializer with:
class PartialChartSerializer(serializers.ModelSerializer):
month = serializers.IntegerSerializer()
profit = serializers.IntegerField()
class Meta:
model = Transactions
fields = ['month', 'profit']
class ProfitChartSerializer(serializers.Serializer):
year = serializers.IntegerField()
data = PartialChartSerializer(many=True)
and feed the items to the serializer as:
from itertools import groupby
from operator import itemgetter
@api_view(['GET'])
@permission_classes([IsAuthenticatedOrReadOnly])
def profit_chart(request):
queryset = (
Transactions.objects.values(
month=ExtractMonth('date'), year=ExtractYear('date')
)
.annotate(profit=Sum(F('sale_price')) - Sum(F('purchase_price')))
.order_by('month')
)
serializer = ProfitChartSerializer(
[
{'year': k, 'data': list(vs)}
for k, vs in groupby(queryset, itemgetter('year'))
],
many=True,
)
return Response(serializer.data, status=status.HTTP_200_OK)
Note: Normally a Django model is given a singular name [django-antipatterns], so
Transaction
instead of.Transactions