javascript - 如何使用 Django REST Framework 保存嵌套的 Backbone 模型

标签 javascript python django backbone.js django-rest-framework

我正在尝试快速保存一系列与外键相关的项目。保存父项后,我在创建子项时使用父项返回的 id。

这有效一次或两次,但在第二次或第三次时,我收到消息:

{"parent_id":["Invalid pk \"5063\" - object does not exist."]}

我已经验证:

  • 发送来创建相关项目的 ID 实际上与保存父项目后在 done() 中返回的 ID 相同

  • 如果我在创建子项之前添加延迟,我可以检查数据库并验证父项是否确实已创建并保存到数据库

  • 如果我在创建子项之前添加足够长的延迟(约 15 秒),则不会产生错误

由于 Backbone.js 前端似乎正在发送有效的 POST 请求,并且项目已立即正确写入数据库,因此我认为这是 Django 问题。

Backbone.js 代码

var i = 0;

function createNew() {
    var parent = ParentObjects.add({name: "New Parent Item"});
    parent.save().done(function(var attributes, stuff, stuff) {
        var id = attributes.id;
        var child = ChildObjects.add({name: "New Child Item", parent_id: id});
        child.save().done(function() {
            i++;
            if (i < 10) {
                createNew();
            }
        });
    });
}

Django Rest框架代码

class Parent(Model):
    name = models.CharField(max_length=200)

class Child(Model):
    parent = models.ForeignKey(Parent, related_name="children")
    name = models.CharField(max_length=200)

class ParentSerializer(ModelSerializer):
    class Meta:
        model = Parent

class ChildSerializer(ModelSerializer):
    parent_id = serializers.PrimaryKeyRelatedField(
        source='parent',
        queryset=Parent.objects.all(),
    )

    class Meta:
        model = Child
        exclude = ('parent', )

class ChildViewSet(ModelViewSet):
    queryset = Child.objects.all()
    serializer_class = ChildSerializer

class ParentViewSet(ModelViewSet):
    queryset = Parent.objects.all()
    serializer_class = ParentSerializer

数据库是Postgresql。

最佳答案

看起来在第一个请求成功但尚未进入数据库的情况下发生了竞争条件,可能只是在该请求的线程中的缓存中。然后,后续调用到达,创建另一个线程来处理它,但父线程尚未真正位于数据库中,因此失败。

如何使用 Backbone 保存嵌套模型?

Backbone 的经验法则是不要将请求一个接一个地循环到 API。

相反,将整个对象发送到 API。 外键是一个关系数据库概念,您应该尽量避免在前端执行数据库/后端工作。

例如,父项的 attributes可以用来同时创建父级及其子级:

ParentObjects.create({
    name: "New Parent Item",
    children: [
        { name: "New Child Item" }
    ]
});

后端应该返回:

{
    id: "23",
    name: "New Parent Item",
    children: [
        { id: "35", name: "New Child Item", parent: "23" }
    ]
}

如何使用 Django REST Framework (DRF) 保存嵌套模型?

自版本 3 起,DRF 提供 writable nested representation所以它与上面的 Backbone 示例几乎是开箱即用的。您只需要为子模型字段提供序列化器并覆盖 create方法。

这是文档中的一个示例,具有简单的关系 User <- Profile :

class UserSerializer(serializers.ModelSerializer):
    profile = ProfileSerializer()

    class Meta:
        model = User
        fields = ('username', 'email', 'profile')

    def create(self, validated_data):
        profile_data = validated_data.pop('profile')
        user = User.objects.create(**validated_data)
        Profile.objects.create(user=user, **profile_data)
        return user

关于javascript - 如何使用 Django REST Framework 保存嵌套的 Backbone 模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41522558/

相关文章:

javascript - Javascript 中的语法/逻辑检查器?

python - Django:如何在我的模板中有效显示数据?

python - 将用户导入到 USER 模型时 Django 中的密码加密

javascript - 从 JSON 模式创建 JSON 实例

javascript - AngularJS 弹出窗口 - 点击主体时隐藏(内部 fiddle )

python - XML 到 CSV 转换器

python - 如何在 python 中实现负无穷大?

python - 'ReverseManyToOneDescriptor' 对象没有属性 'all'

c# - 显示警报时获取警报内容

python - 是否有可能 "hack"Python 的打印功能?