【问题标题】:ManyToMany Through Field Serialization多对多通过字段序列化
【发布时间】:2015-08-26 10:39:54
【问题描述】:

我在按数量序列化我的商品/订单时遇到问题。

我得到的结果:

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

【问题讨论】:

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


    【解决方案1】:

    你可以这样使用它:

    class OrderItemSerializer(serializers.ModelSerializer):
        class Meta:
            model = Order.items.through
            fields = ('order', 'item', 'quantity')
    
    
    class OrderSerializer(serializers.ModelSerializer):
        items = OrderItemSerializer(source='orderitem_set', many=True)
        class Meta:
            model = Order
            fields = ('your_order_fields', 'items')
    
    

    注意:您必须将items 字段添加到OrderSerializer

    【讨论】:

      【解决方案2】:

      通过将OrderSerializer items 字段更改为OrderItemField,我可以使用self.root.instance 回到根Order,然后将其与value 结合使用,这是一个Item 实例,构建查询以查找OrderItem 对象以获取数量。然后我可以使用我的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',)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-16
        • 1970-01-01
        • 2018-09-21
        • 1970-01-01
        • 1970-01-01
        • 2018-10-14
        • 1970-01-01
        相关资源
        最近更新 更多