ManyToMany通过现场序列化

时间:2015-06-10 23:09:46

标签: python json django serialization django-rest-framework

我在序列化我的物品/订单时遇到问题。

我得到的结果:

{
"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
}

我想要的结果:

{
"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
}

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)

串行器

我意识到我的序列化程序正在将orderitem_set放入我的json中,但我无法弄清楚如何将quantity数据转换为items而不是循环浏览项目和orderitem_set的自定义视图,并向项目添加quantity。但这很糟糕,我希望有一种方法可以用框架内置的东西来做到这一点,或者至少做到这一点,所以我不必为每个视图做到这一点。

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',)

视图

这个观点给了我正在寻找的东西,但它太可怕了。特别是当我有其他观点时会给我一个订单列表而不是一个订单。

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)

1 个答案:

答案 0 :(得分:0)

通过将OrderSerializer items字段更改为OrderItemField,我可以使用Order返回到根self.root.instance,然后将其用于与valueItem实例相结合,构建查询以查找OrderItem对象以获取数量。然后,我可以使用我的Item获取序列化ItemSerializer,然后将数量附加到该数据。

这样做可以应用于我的所有订单视图,而且不那么混乱。如果有更好的方法请告诉我!

<强>串行器

class OrderItemField(serializers.RelatedField):
    def to_representation(self, value):
        if type(self.root.instance) == list:
            self.root.instance = self.root.instance[0]
        order_item = OrderItem.objects.filter(item=value, order=self.root.instance).first()
        quantity = order_item.quantity
        value = ItemSerializer(value).data
        value['quantity'] = quantity
        return value


class OrderSerializer(serializers.ModelSerializer):
    _current_status = StatusSerializer(required=False, many=False)
    items = OrderItemField(many=True, read_only=True)

    class Meta:
        model = Order
        exclude = ('user',)