2017-01-07 16 views
1

外部キーに関連する一連の項目を迅速に保存しようとしています。親アイテムを保存した後、子アイテムを作成するときに親アイテムの返されたIDを使用します。Django REST Frameworkでネストされたバックボーンモデルを保存するには

これは一度か二度動作しますが、第二ま​​たは第三の時間に、私はメッセージを取得する:

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

私がいることを確認しました:

  • 関連を作成するために送信される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(); 
      } 
     }); 
    }); 
} 

ジャンゴレストフレームワークコード

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です。

答えて

1

それは、最初の要求が成功したところ、レース条件が起こっているのように見えますが、データベースの中にまだ残っている、ちょうどこのリクエストのスレッドでキャッシュ内おそらく。それから、後続の呼び出しが到着し、それを処理する別のスレッドが作成されますが、親のはまだ実際にはではありません。

Backboneでネストされたモデルを保存するにはどうすればよいですか?

バックボーンでの経験則はです。APIへのリクエストを次々にループしません。

代わりに、オブジェクト全体をAPIに送信します。 外部キーはリレーショナルデータベースの概念です。フロントエンドでデータベース/バックエンドジョブを実行しないようにしてください。

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

をたとえば、親のattributesが同時に親とその子の両方を作成するために使用することができ

Django RESTフレームワーク(DRF)で?

バージョン3以降、DRFにはwritable nested representationが提供されているため、上記のバックボーンの例でほぼそのまま使用できます。子モデルフィールドのシリアライザを用意し、createメソッドをオーバーライドするだけで済みます。

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 
+0

ありがとう:ここ

は単純な関係User <- Profileとドキュメントからの例です!それは良い代替ソリューションのようだ。私はまだ子供が保存される前に5秒の遅延を追加し、データベースの親テーブルをチェックすると、新しい親がそこにあるが、子を保存することはまだ失敗するので、これがどうして正確に起こっているのか混乱しているそのような親は存在しなかった。 –

+0

@ZacharyBlackwood実際に保存する前にレスポンスを作成するDjangoの最適化やどこかの設定が起こっているのかを知るのは本当に難しいです。全体の保存を単一の要求にすることは、デバッグを大幅に簡素化します。また、SOの最高のおかげでupvotes;) –

関連する問題