Skip to main content
 首页 » 编程设计

python之django-tastypie : Related data not saving

2025年04月02日32jpfss

我的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", 
    } 
  ] 
} 

现在根据 tasty 文档,

Tastypie encourages “round-trippable” data, which means the data you can GET should be able to be POST/PUT’d back to recreate the same object. If you’re ever in question about what you should send, do a GET on another object & see what Tastypie thinks it should look like.

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

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

请您参考如下方法:

试试这个:

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