質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

REST

REST(Representational State Transfer)はwebアプリケーションの構築スタイルの一種です。HTTP GET/POSTによってリクエストを送信し、レスポンスはXMLで返されます。SOAPのようなRPCの構築と比べるとサーバからクライアントを分離することが出来る為、人気です。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

Q&A

解決済

1回答

4256閲覧

AjaxでinputタグのファイルをDjango REST FrameworkのAPIに渡したらMultiValueDictのkeyに入れられてしまう

shimeji_forest

総合スコア6

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

REST

REST(Representational State Transfer)はwebアプリケーションの構築スタイルの一種です。HTTP GET/POSTによってリクエストを送信し、レスポンスはXMLで返されます。SOAPのようなRPCの構築と比べるとサーバからクライアントを分離することが出来る為、人気です。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

0グッド

1クリップ

投稿2018/07/02 10:21

Python 3.6.5
Django 2.0.6

Django REST FrameworkのAPIに対してjQueryを利用したAjaxでinputタグに読み込んだ画像ファイルを送信したところ、
データがrequest.POSTのkeyにMultiValueDictとして入力されてしまってrequest.POST.get()で取得することが出来ません。
どうしたら通常の様なkeyに対するvalueとしてrequest.POSTへ入力される様になるのでしょうか。

データの送信処理自体はページからデータをAPIに対してjQueryを利用したAjaxでサーバへ送信して登録するという処理を既に作成していて、
Ajaxで送信されたデータが通常のrequest.POST.get()で取得可能な状態であることを確認してから流用しています。

実行時の出力
10
None
<QueryDict: {'[object Object]': ['']}>
<MultiValueDict: {'[object Object]': ['']}>
(省略)
AttributeError: 'MultiValueDict' object has no attribute 'iteritems'

AjaxにcontentType: 'multipart/form-data',を追加した場合、
10
None
<QueryDict: {}>
<MultiValueDict: {}>
(中略)
multipartparser.py", line 72, in init
raise MultiPartParserError('Invalid boundary in multipart: %s' % boundary.decode())
AttributeError: 'NoneType' object has no attribute 'decode'
というエラーが幾つも出力されます。

JavaScript

1pcreate.js 2var input_file_change = function () { 3 input_file = document.getElementById('input_file'); 4 files = input_file.files; 5 if (files[0] != 'undefined') { 6 var fd = new FormData(); 7 var id = document.getElementById('photo_id').value; 8 for (var i = 0; i < files.length; i++) { 9 var file = files[i]; 10 11 fd.append('file', file); 12 } 13 14 $.ajax({ 15 url: 'http://localhost:8000/api/submit_picture/', 16 type: 'POST', 17 data: { 18 'files': fd, 19 'id': id, 20 }, 21 processData: false, 22 dataType: 'json', 23// contentType: 'multipart/form-data', 24 success: function(response) { 25 console.log('success'); 26 }, 27 error: function(e, x, r) { 28 console.log(e); 29 } 30 }); 31 } 32};

HTML

1pcreate.html 2<div class="col"> 3 <button class="btn btn-outline-primary" id="add_picture">画像の追加</button> 4 <form method="POST" enctype="multipart/form-data" id="save_picture"> 5 <input type="file" name="files[]" style="display: none" id="input_file" multiple> 6 <input type="hidden" value="{{ photo_id }}" id="photo_id"> 7 {% csrf_token %} 8 <input type="submit" style="display: block" id="submit_picture" name="submit_picture"> 9 </form> 10</div> 11

Python

1views.py 2class PCreate(generic.TemplateView): 3 template_name = 'photo_app/pcreate.html' 4 5 def get_context_data(self, **kwargs): 6 7 context = super(PCreate, self).get_context_data(**kwargs) 8 context['photo_id'] = '' 9 return context 10 11class PictureSave(viewsets.ModelViewSet): 12 13 queryset = Photo.objects.all() 14 serializer_class = PictureSaveSerializer 15 16 def create(self, request, *args, **kwargs): 17 18 json_ary = [] 19 if request.method == 'POST': 20 login_user_id = request.user.id 21 photo_id = request.POST.get('id') 22 files = request.POST.get('files') 23 24 print(login_user_id) 25 print(photo_id) 26 print(request.POST) 27 print(files) 28 29 for filename, file in request.FILES.iteritems(): 30 print(file) 31 dict = [] 32 33 photoObject = Photo( 34 title=request.FILES[filename].name, 35 image=file, 36 user_id = login_user_id, 37 photo_id=id 38 ) 39 photoObject.save() 40 41 dict.append({ 42 'id':'%s' % photoObject.id, 43 'filename': request.FILES[filename].name, 44 'file': file, 45 }) 46 47 json_ary.append(dict) 48 49 return JsonResponse({"data":json_ary})

Python

1models.py 2def get_upload_to(instance, filename): 3 name = str(uuid.uuid4()).replace('-', '') 4 extension = os.path.splitext(filename)[-1] 5 return os.path.join(str(instance.photobook_id.id), name, extension) 6 7class Photo(models.Model): 8 9 use_in_migrations = True 10 11 # ユーザーID 12 user_id = models.PositiveIntegerField(_('ユーザーID'), default=0, blank=False) 13 # 画像タイトル 14 title = models.CharField(max_length=255,) 15 # 画像データ 16 image = models.ImageField(upload_to=get_upload_to, null=True, blank=True,) 17 # 登録日時 18 date_joined = models.DateTimeField(_('登録日時'), default=timezone.now) 19 20 class Meta: 21 app_label = 'photobook_app'

Python

1serializer.py 2class PictureSaveSerializer(serializers.ModelSerializer): 3 4 class Meta: 5 model = Photo 6 fields = '__all__'

Python

1urls.py 2#写真の追加処理 3router.register(r'submit_picture', PictureSave) 4 5urlpatterns = [ 6 path('pcreate/', views.PCreate.as_view(), name='pcreate'), 7]

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

本質的な解決になりませんが、
時間の都合上からREST APIをDjango REST Frameworkで統一することを諦めて、defでrequest.POSTを受けた時にのみ処理する様にして実装することにしました。

JavaScript

1pcreate.js 2 3var files; 4 5//inputタグ内のファイルが変更された場合 6var input_file_change = function () { 7 input_file = document.getElementById('input_file'); 8 files = input_file.files; 9 if (files[0] != 'undefined') { 10 var fd = new FormData($("#save_picture").get(0)); 11 12 $.ajax({ 13 url: 'http://localhost:8000/submit_picture/', 14 type: 'POST', 15 data: fd, 16 processData: false, 17 contentType: false, 18 success: function(response) { 19 console.log(response); 20 console.log(response.data[0][0]); 21 }, 22 error: function(e, x, r) { 23 console.log(e); 24 } 25 }); 26 } 27}; 28

Python

1urls.py 2 3# ページ設定 4urlpatterns = [ 5 path('pcreate/', views.PCreate.as_view(), name='pcreate'), 6 path('submit_picture/', views.PictureSave, name='upload_save'), 7]

Python

1models.py 2 3from django.db import models 4from django.utils.translation import ugettext_lazy as _ 5from django.utils import timezone 6import uuid 7import os 8 9def get_upload_to(instance, filename): 10 name = str(uuid.uuid4()).replace('-', '') 11 extension = os.path.splitext(filename)[-1] 12 return os.path.join(str(instance.user_id), name + extension) 13 14# 画像クラス 15class Photo(models.Model): 16 17 use_in_migrations = True 18 19 # 画像タイトル 20 title = models.CharField(max_length=255,) 21 # 画像データ 22 image = models.ImageField(upload_to=get_upload_to, null=True, blank=True,) 23 # ユーザーID 24 user_id = models.PositiveIntegerField(_('ユーザーID'), default=0, blank=False) 25 # 登録日時 26 date_joined = models.DateTimeField(_('登録日時'), default=timezone.now) 27 28 class Meta: 29 app_label = 'photo_app'

Python

1views.py 2 3from django.http import JsonResponse 4from django.core import serializers 5from photobook_app.models.image import Photo 6import base64 7def PictureSave(request): 8 if request.method == 'POST': 9 try: 10 login_user_id = request.user.id 11 12 json_ary = [] 13 for file in request.FILES.getlist("files[]"): 14 print(file) 15 dict = [] 16 17 photoObject = Photo( 18 title=file.name, 19 image=file, 20 user_id = login_user_id, 21 ) 22 photoObject.save() 23 24 # 画像ファイルを読み込んでBASE64形式に変換 25 image_path = photoObject.image.path 26 b64 = base64.encodestring(open(image_path, 'rb').read()).decode('utf-8') 27 28 dict.append({ 29 'id':'%s' % photoObject.id, 30 'filename': photoObject.title, 31 'file': 'data:image/jpg;base64,%s' % b64, 32 }) 33 json_ary.append(dict) 34 35 response = HttpResponse(dict, content_type="application/json") 36 return JsonResponse({"data":json_ary}) 37 except Exception as err: 38 raise err

投稿2018/07/03 06:04

編集2018/07/03 09:07
shimeji_forest

総合スコア6

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問