【问题标题】:django-tastypie : Related data not savingdjango-tastypie:相关数据未保存
【发布时间】:2016-07-01 18:45:05
【问题描述】:

我的models.py

class Orders(models.Model):
    order_id = models.CharField(max_length=7, primary_key=True)
    users = models.ForeignKey(ProductUsers, on_delete=models.DO_NOTHING)
    address = models.ForeignKey(ProductUsersAddress, on_delete=models.DO_NOTHING)
    payment_method = models.CharField(default='COD', max_length=20, choices=PAYMENT_METHOD)

class OrderedProduct(models.Model):
    products = models.ForeignKey(Products, on_delete=models.DO_NOTHING)
    orders = models.ForeignKey(Orders, on_delete=models.CASCADE)
    quantity = models.IntegerField(default=0)
    price = models.DecimalField(default=0.00, max_digits=5, decimal_places=2, blank=False)

我的resources.py

class OrdersResource(ModelResource):

    ordered_products = fields.ToManyField('orders.resources.OrderedProductResource',
                                          attribute=lambda bundle: OrderedProduct.objects.filter(orders=bundle.obj),
                                          related_name='orders', full=True, null=True)

    contact_no = fields.ForeignKey(ProductUsersResource, 'users')
    address = fields.ForeignKey(ProductUsersAddressResource, 'address')

    class Meta:
        queryset = Orders.objects.all()
        resource_name = 'orders'
        include_resource_uri = False
        collection_name = 'orders'
        allowed_methods = ['get', 'post']
        always_return_data = True

class OrderedProductResource(ModelResource):
    products = fields.ForeignKey(ProductsResource, 'products')
    orders = fields.ForeignKey(OrdersResource, 'orders')

    class Meta:
        queryset = OrderedProduct.objects.all()
        resource_name = 'ordered_products'
        excludes = ['id']
        include_resource_uri = False

我使用 Django-Admin 输入数据。 当我点击时,http://localhost:8000/orders/,我明白了,

{
  "orders": [
    {
      "address": "/api/v1/address/1",
      "contact_no": "/api/v1/users/8269661606",
      "order_id": "KJLSWI",
      "ordered_products": [
        {
          "orders": "/api/v1/orders/KJLSWI",
          "price": "40.00",
          "products": "/api/v1/products/1",
          "quantity": 2
        },
        {
          "orders": "/api/v1/orders/KJLSWI",
          "price": "70.00",
          "products": "/api/v1/products/2",
          "quantity": 4
        },
        {
          "orders": "/api/v1/orders/KJLSWI",
          "price": "67.00",
          "products": "/api/v1/products/3",
          "quantity": 7
        }
      ],
      "payment_method": "COD",
    }
  ]
}

现在根据美味的文档,

Tastypie 鼓励“可往返”的数据,这意味着您的数据 GET 应该能够被 POST/PUT 回来重新创建相同的 目的。 如果您对应该发送的内容有任何疑问,请执行 GET on 另一个对象,看看 Tastypie 认为它应该是什么样子。

但是当我通过更改主键发布相同的数据时,

{
  "address": "/api/v1/address/1",
  "contact_no": "/api/v1/users/8269661606",
  "order_id": "ABCDE",
  "ordered_products": [
    {
      "orders": "/api/v1/orders/ABCDE",
      "price": "40.00",
      "products": "/api/v1/products/1",
      "quantity": 2
    },
    {
      "orders": "/api/v1/orders/ABCDE",
      "price": "70.00",
      "products": "/api/v1/products/2",
      "quantity": 4
    },
    {
      "orders": "/api/v1/orders/ABCDE",
      "price": "67.00",
      "products": "/api/v1/products/3",
      "quantity": 7
    }
  ],
  "payment_method": "COD",
}

我得到回应,

{
  "address": "/api/v1/address/1",
  "contact_no": "/api/v1/users/8269661606",
  "ordered_products": [],
  "payment_method": "COD",
}

我在模型OrderedProduct 中的数据没有被保存。为什么YYYYYY ??????

【问题讨论】:

  • 您是否在 django shell 上进行了验证并在您发布之前和之后查询所有对象?你看到了什么?
  • @ShangWang 是的,我做到了.. 数据保存在“Orders”表中,但未保存在“OrderedProduct”中。
  • 我知道,我必须对相关名称做一些事情,我尝试了几乎所有可能的方法,但它对我不起作用。我在我的 ToManyField 中添加了相关的 _name。但结果还是一样。

标签: python django api rest tastypie


【解决方案1】:

试试这个:

def hydrate_m2m(self, bundle):
    for ordered_product in bundle.data['ordered_products']:
        if isinstance(ordered_product, dict):
            ordered_product.update({'orders': bundle.obj})

    return super(OrdersResource, self).hydrate_m2m(bundle)

并从 ordered_products JSON 中删除 orders

并将attribute=lambda bundle: OrderedProduct.objects.filter(orders=bundle.obj) 替换为orders

并将 related_name='orders' 从资源移动到模型。

最后:

型号:

class OrderedProduct(models.Model):
    products = models.ForeignKey(Products, on_delete=models.DO_NOTHING)
    orders = models.ForeignKey(Orders, on_delete=models.CASCADE, related_name='orders')
    quantity = models.IntegerField(default=0)
    price = models.DecimalField(default=0.00, max_digits=5, decimal_places=2, blank=False)

资源:

class OrdersResource(ModelResource):

    ordered_products = fields.ToManyField('orders.resources.OrderedProductResource',
                                          'orders', full=True, null=True)

    contact_no = fields.ForeignKey(ProductUsersResource, 'users')
    address = fields.ForeignKey(ProductUsersAddressResource, 'address')

    class Meta:
        queryset = Orders.objects.all()
        resource_name = 'orders'
        include_resource_uri = False
        collection_name = 'orders'
        allowed_methods = ['get', 'post']
        always_return_data = True

    def hydrate_m2m(self, bundle):
        for ordered_product in bundle.data['ordered_products']:
            if isinstance(ordered_product, dict):
                ordered_product.update({'orders': bundle.obj})

        return super(OrdersResource, self).hydrate_m2m(bundle)

和 POST 数据:

{
  "address": "/api/v1/address/1",
  "contact_no": "/api/v1/users/8269661606",
  "order_id": "ABCDE",
  "ordered_products": [
    {
      "price": "40.00",
      "products": "/api/v1/products/1",
      "quantity": 2
    },
    {
      "price": "70.00",
      "products": "/api/v1/products/2",
      "quantity": 4
    },
    {
      "price": "67.00",
      "products": "/api/v1/products/3",
      "quantity": 7
    }
  ],
  "payment_method": "COD",
}

【讨论】:

  • 像您在hydrate_m2m 中所做的那样为每个ordered_product 添加“订单”,如果我在alter_deserialized_detail_data 中这样做会不会有什么坏处?这可能是个愚蠢的问题,我是 django 的初学者,请考虑一下。 :)
  • 在这种情况下,您需要bundle.obj。在alter_deserialized_detail_data 你没有。在hydrate_m2m 你有它。
  • 有什么办法,我也可以为addresscontact_noproducts 做同样的事情吗?就像不在帖子数据中添加/api/v1/resource_name,而是使用tastepie添加它们。
猜你喜欢
  • 2015-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-01
  • 2016-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多