Reputation: 2384
I got following models:
class OrderItem(models.Model):
ordered_amount = models.IntegerField(validators=[MinValueValidator(0)])
amount = models.IntegerField(default=0)
order = models.ForeignKey(
Order, on_delete=models.CASCADE, related_name="order_items"
)
class Order(models.Model):
reference = models.CharField(max_length=50)
purchase_order = models.CharField(max_length=15, blank=True, null=True)
I'm now writing a serializer for listing orders. In this OrderSerializer I need to access amount and ordered_amount in the OrderItem class. How do I do this? This is What I have now:
class AdminOrderListSerializer(serializers.ModelSerializer):
amount = serializers.IntegerField()
ordered_amount = serializers.IntegerField()
class Meta:
model = Order
fields = [
"purchase_order",
"reference",
"amount",
"ordered_amount",
]
# noinspection PyMethodMayBeStatic
def validate_amount(self, order):
if order.order_items.amount:
return order.order_items.amount
return
# noinspection PyMethodMayBeStatic
def validate_ordered_amount(self, order):
if order.order_items.ordered_amount:
return order.order_items.ordered_amount
return
This gives me following error:
AttributeError: Got AttributeError when attempting to get a value for field amount
on serializer AdminOrderItemListSerializer
.
The serializer field might be named incorrectly and not match any attribute or key on the Order
instance.
Original exception text was: 'Order' object has no attribute 'amount'.
Upvotes: 0
Views: 33
Reputation: 51988
There are many ways to that, one of them is SerializerMethodField
:
from django.db.models import Sum
class AdminOrderListSerializer(serializers.ModelSerializer):
amount = serializers.SerializerMethodField()
ordered_amount = serializers.SerializerMethodField()
def get_amount(self,obj):
return obj.order_items.aggregate(sum=Sum('amount'))['sum']
def get_ordered_amount(self,obj):
return obj.order_items.aggregate(sum=Sum('order_amount'))['sum']
Another way of achieving this is to annotate
the data to queryset, and access them in serializer. For that, you need to change in view:
class SomeView(ListAPIView):
queryset = Order.objects.annotate(amount=Sum('order_items__amount'),order_amount=Sum('order_items__order_amount'))
This is a optimized solution because it reduces database hits(it only hits once).
Upvotes: 1