I am having problems serializing my items/orders with quantity.
Results I am getting:
{
"id": 1,
"_current_status": null,
"orderitem_set": [
{
"item_id": 2,
"quantity": 5
},
{
"item_id": 1,
"quantity": 1
}
],
"items": [
{
"id": 2,
"name": "Blue Shoe",
"description": "Sweet blue shoe bro",
"weight": "99.99",
"price": "99.99"
},
{
"id": 1,
"name": "Red Shoe",
"description": "sweet red shoe bro",
"weight": "1.00",
"price": "100.00"
}
],
"_last_modified": "2015-06-10T22:32:08.007833Z",
"_weight": "500.95",
"_total_price": "599.95",
"placed": false,
"date_placed": null
}
Results I want:
{
"id": 1,
"_current_status": null,
"items": [
{
"id": 2,
"name": "Blue Shoe",
"description": "Sweet blue shoe bro",
"weight": "99.99",
"price": "99.99",
"quantity": 5
},
{
"id": 1,
"name": "Red Shoe",
"description": "sweet red shoe bro",
"weight": "1.00",
"price": "100.00",
"quantity": 1
}
],
"_last_modified": "2015-06-10T22:32:08.007833Z",
"_weight": "500.95",
"_total_price": "599.95",
"placed": false,
"date_placed": null
}
Classes
class Order(models.Model):
_current_status = models.ForeignKey("main.Status", blank=True, null=True)
_last_modified = models.DateTimeField(auto_now=True)
_weight = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
_total_price = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
user = models.ForeignKey("main.ShopUser")
items = models.ManyToManyField("main.Item", through='main.OrderItem')
placed = models.BooleanField(default=False)
date_placed = models.DateTimeField(null=True, blank=True)
class OrderItem(models.Model):
order = models.ForeignKey('main.Order')
item = models.ForeignKey('main.Item')
quantity = models.IntegerField(default=1)
Serializers
I realize that my serializer is what is putting the orderitem_set
into my json but I couldn't figure out how to get the quantity
data into items
other than in a custom view that loops through the items and the orderitem_set
and adds a quantity
to items. But that is just terrible and I was hoping there was a way to do this with the built in stuff with the framework or at least make it so I don't have to do that for every view.
class OrderItemField(serializers.RelatedField):
def to_representation(self, value):
return {'item_id': value.item_id, 'quantity': value.quantity}
class OrderSerializer(serializers.ModelSerializer):
_current_status = StatusSerializer(required=False, many=False)
orderitem_set = OrderItemField(read_only=True, many=True)
items = ItemSerializer(required=True, many=True)
class Meta:
model = Order
exclude = ('user',)
The view
This view gives me what I am looking for, but it is just terrible. Especially when I have other views that would be giving me a list of orders vs just a single order.
def set_quantities(data):
# Gets the quantity for each item and then appends it to each item instead of having 'orderitem_set'
for order_item in data['orderitem_set']:
for item in data['items']:
if item['id'] == order_item['item_id']:
item['quantity'] = order_item['quantity']
del data['orderitem_set']
return data
def get(self, request, *args, **kwargs):
serializer = self.get_serializer(self.get_object())
data = set_quantities(serializer.data)
return Response(data, status=status.HTTP_200_OK)
By changing the
OrderSerializer
items
field to be anOrderItemField
I was able to get back to rootOrder
by usingself.root.instance
and then using that in conjuction with thevalue
, which is anItem
instance, build a query to find theOrderItem
object to get the quantity. Then I can get a serializedItem
using myItemSerializer
and just append the quantity to that data.Doing it this way applies to all of my order views and it is a lot less messy. If there is a better way please let me know!
Serializers