Tastypie - POST时嵌套资源被更新而非创建

4 投票
1 回答
1531 浏览
提问于 2025-04-17 15:10

我正在尝试发送一个资源,这个资源基本上是一个子资源的列表。以下是我的资源:

class MovementResource(ModelResource):
    transactions = fields.ToManyField('stock.api.TransactionResource',
        'transaction_set', related_name='movement', full=True)

    class Meta:
        queryset = Movement.objects.all()
        resource_name = 'movement'
        always_return_data = True
        authorization = Authorization()

class TransactionResource(ModelResource):
    movement = fields.ToOneField(MovementResource, 'movement')
    product = fields.ToOneField(ProductResource, 'product', full=True)

    class Meta:
        queryset = Transaction.objects.all()
        resource_name = 'transaction'
        authorization = Authorization()

这个资源表示库存中各种产品的移动情况。移动表单只是一个内联列表,每个交易对应一个条目。它根本没有使用django的表单。

我的问题是,当我尝试发送一个移动请求,并指定要创建的交易列表时,我发现Tastypie并没有插入新的交易,而是更新了一个已经存在的交易。这是一个POST请求的JSON,表示只有一个交易的移动:

{
    'transactions': [
        {
            'product': '/api/v1/product/3/',
            'quantity': '1'
        }
    ]
}

响应的JSON显示移动已经创建,但交易的ID是之前存在的,并且产品和数量是相同的。这个交易对象中的移动外键(FK)已经更新为指向新创建的移动。响应数据:

{
    'date': '2013-02-07 ···',
    'id': '66',
    'resource_uri': '/api/v1/movement/66/',
    'transactions': [
        {
            'date': '2013-01-30 ···', # Should be the same as parent movement's date
            'id': '30',
            'movement': '/api/v1/movement/66/',
            'product': { ··· product resource data ··· },
            'quantity': '1',
            'resource_uri': '/api/v1/transaction/30/',
        }
    ]
}

我是不是漏掉了什么?Tastypie难道不应该在这个列表端点的POST请求中创建嵌套资源吗?我尝试过使用ForeignKey和ToOneField指向MovementResource,看看是否会有区别,但都没有成功。(实际上我也找不到这两者之间的区别。)

谢谢!

1 个回答

6

我也遇到了同样的问题。

经过几个小时的挣扎,我找到了一种解决办法,可以强制在相关资源上进行POST操作:如果你给嵌套资源的主键传递一个null值,那么tastypie就会创建一个新的,而不是更新一个已有的。

如果你发送以下内容,你应该能得到你想要的效果:

{
   'transactions': [
        {
            'product': '/api/v1/product/3/',
            'quantity': '1',
            'id': null
        }
   ]
}

撰写回答