2015-06-10 60 views
2

我有問題序列化我的項目/訂單與數量。ManyToMany通過現場序列化

結果我得到:

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

回答

0

通過改變OrderSerializeritems場是一個OrderItemField我能夠通過使用self.root.instance,然後使用與value,這是一個Item實例一起選擇,生成一個查詢找到要回根OrderOrderItem對象獲取數量。然後我可以使用我的ItemSerializer獲得序列號Item,並將數量附加到該數據。

這樣做適用於我所有的訂單視圖,並且不那麼混亂。如果有更好的方法,請讓我知道!

串行器

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