2017-12-05 7 views
1

でJSONを入れ子になりましたか?このことを考えるとジャンゴRESTフレームワークネストされたシリアライザとPOSTは、私はRESTネストされたシリアライザをDjangoのためのファイル(画像)を含むネストされたデータでPOSTリクエストを送信するにはどうすればよいのファイル

は、オブジェクトをJS:

bookData: { 
    title: 'Anne of Green Gables', 
    coverImage: File(123456), 
    pages: 123, 
    author: { 
     name: 'Lucy Maud Montgomery', 
     born: 1874, 
     profilepicture_set: [ 
      {file: File(234567), description: 'Young L. M. Montgomery'}, 
      {file: File(234568), description: 'Old L. M. Montgomery} 
     ], 
     quote_set: [ 
      {text: "I'm so glad I live in a world where there are Octobers."}, 
      {text: "True friends are always together in spirit."}, 
     ] 
    }, 

} 

私は私のDjangoのRESTのAPI(私はフロントエンドにVueJSを使用しますが、これは本当に重要ではありません)へのPOSTリクエストを送信したいです。

# views.py 
class CreateBookView(generics.CreateAPIView): 
    serializer_class = CreateBookSerializer 
    queryset = Book.objects.all() 

# serializers.py 
class CreateBookSerializer(serializers.ModelSerializer): 
    author = CreateAuthorSerializer() 

    class Meta: 
     model = Book 
     fields = ('title', 'pages', 'author') 

    @transaction.atomic 
    def create(self, validated_data): 
     author_data = validated_data.pop('author') 
     uploader = self.context['request'].user 
     book = Book.objects.create(uploader=uploader, **validated_data) 

     Author.objects.create(book=book, **author_data) 

     return book 


# models.py 
class AuthorManager(models.Manager): 

    def create(self, **author_data): 
     quotes_data = author_data.pop('quote_set') 
     photos_data = author_data.pop('profilepicture_set') 

     author = Author(**author_data) 
     author.save() 

     for quote_data in quotes_data: 
      Quote.objects.create(author=author, **quote_data) 

     for photo_data in photos_data : 
      ProfilePicture.objects.create(author=author, **photo_data) 

     return author 

## Skipping the CreateAuthorSerializer, Quote and ProfilePicture Managers as they are analogous. 
## Assume one Author can only write one Book (OneToOneField). No need to look the name up for existing Authors. 

私はVueJSにおけるフロントエンドでデータを送信する方法についていくつかの情報を追加したいEDIT

sendData(){ 
    var fd = new FormData() 
    var bookData = { 
     title: this.$store.getters.title, # 'Anne of Green Gables" 
     coverImage: this.$store.getters.coverImage, # File(somesize) 
     pages: this.$store.getters.pages, # 123 
     author: this.$store.getters.author, # nested object 
     ... 
    } 
    fd = objectToFormData(bookData, fd) # external function, see below 
    this.$http.post('api/endpoint/create/', fd, headers: { 
     'Content-Type': 'multipart/form-data', 
     'X-CSRFToken': Cookies.get('csrftoken'), 
     } 
    }).then(...) 
} 

sendData()は、ボタンクリックで呼び出されます。 objectToFormDataは平坦状にネストされたオブジェクトを変換NPM (click)から外部LIBです。

この溶液(ならびに@Sajiザビエルの溶液)に問題がrequest.dataが元bookDataオブジェクト構造から遠いとRESTシリアライザによって受け入れられない醜いのQueryDictを含んでいることである(すなわち、authorフィールドであります欠落 - これは真実であり、オブジェクトは平坦化されている)。

<QueryDict: { 
'title': ['Anne of Green Gables'], 
'coverImage':[InMemoryUploadedFile: cover.jpg (image/jpeg)], 
'pages': ['123'], 
'name': ['Lucy Maud Montgomery'], 
'born': ['1874'], 
'profilepicture_set[][description]': ['Young L. M. Montgomery', 'Old L. M. Montgomery'], 
'profilepicture_set[][file]': [ 
    InMemoryUploadedFile: young.jpg (image/jpeg), 
    InMemoryUploadedFile: old.jpg (image/jpeg) 
    ], 
'quote_set[][text]': [ 
    "I'm so glad I live in a world where there are Octobers.", 
    "True friends are always together in spirit." 
    ] 
}> 

どうすればいいですか?それは醜いsoooooのようです。私が考えることは、create()関数を上書きすることです。

class CreateBookView(generics.CreateAPIView): 
    (...) 
    def create(self, request, *args, **kwargs): 
     book_data = {} 
     book_data['title'] = request.data['title'] 
     book_data['pages'] = request.data['pages'] 
     book_data['cover_image'] = request.data['coverImage'] 
     book_data['author'] = {} 
     book_data['author']['name'] = request.data['name'] 
     book_data['author']['born'] = request.data['born'] 
     (...) 
     serializer = self.get_serializer(data=book_data) 
     (...) 

これはフィールドやnestednessのいくつかのレベルの多数を搭載したモデルのための効果的でない非常に醜いソリューション、(この本/著者は単なるおもちゃの一例である)です。私はそれをどのように処理するかを

?私はポストの方法を変えますか(嬉しいですか?request.data形式)、この醜いものを扱いますか?

答えて

0

などDRF documentation

最もパーサをよれば、例えばJSONはファイルのアップロードをサポートしていません。 Djangoの 定期FILE_UPLOAD_HANDLERSは、アップロードされたファイルを処理するために使用されています。

一つの選択肢は、これは私の問題に対処していない

var fd = new FormData(); 
fd.append('title', 'Anne of Green Gables') 
fd.append('author_name', 'Lucy Maud Montgomery') 
fd.append('author_profilepicture_set', files[]) 
$http.post('url', fd, { 
    headers: { 
     'Content-Type': 'multipart/form-data' 
    } 
}); 
+0

(VueJS/AngularJSで動作します)マルチパートデータを送信するためのJavascriptいるFormData APIを使用することです - 私は、データを送信するために管理しますが、要求の形式がありますDRFシリアライザによる処理には非常に不快です。 – Fidd

+0

マルチパートは私の提案ではなく、(などの保存、検査の実施)のようなシリアライザの機能を使用しrequest.POST.get(データ)を使用して、サーバー内のファイルを保存することはないので、シリアライザのための問題を作成する(または別のファイルを処理してできるようになりますデータのシリアライザハンドル休み) –

+0

私は私が同じを探していた時に、他の解決策を見つけることができませんでした、それはきれいな解決策ではないことを知っていると我々はいるFormDataのアプローチのために行く必要があります。 –

関連する問題