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

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

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

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

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Python 3.x

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

REST

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

2回答

5253閲覧

PythonのREST APIから取得したJSONデータをHTML上に埋め込んで表示したい

shimeji_forest

総合スコア6

Django

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

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Python 3.x

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

REST

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2018/05/14 04:00

前提・実現したいこと

Pythonでdjangorestframeworkを使用してデータベースから読み込んだデータをJSON形式で返す処理を作成しています。
上記のREST APIは実際にWebブラウザ上で指定のアドレスへアクセスすればデータが出力されていることを確認しています。
jQueryを用いて上記のREST APIからJSONデータを受け取ってHTMLページへ埋め込む処理を作りたいです。

Python 3.6
Django 2.0.5
django-cors-headers 2.2.0
django-filter 1.1.0
djangorestframework 3.8.2

発生している問題・エラーメッセージ

実際にjQueryのajaxを使用して取得しようとすると以下のエラーが発生してしまいます。

Error: jQuery1800804225095946975_1526269266370 was not called
at Function.error (eval at <anonymous> (jquery-1.8.0.min.js:2), <anonymous>:2:13145)
at c.converters.script json (eval at <anonymous> (jquery-1.8.0.min.js:2), <anonymous>:2:83347)
at cC (eval at <anonymous> (jquery-1.8.0.min.js:2), <anonymous>:2:5874)
at y (eval at <anonymous> (jquery-1.8.0.min.js:2), <anonymous>:2:79888)
at HTMLScriptElement.c.onload.c.onreadystatechange (eval at <anonymous> (jquery-1.8.0.min.js:2), <anonymous>:2:84323)

ただ、Google ChromeのDevTools上でヘッダは200 OKが出ていて、ResponseでもJSONのデータが受け取ることが出来ていますが、ajaxはエラーになってしまいます。

該当のソースコード

・Settings.py

Python

1INSTALLED_APPS = [ 2 'django.contrib.admin', 3 'django.contrib.auth', 4 'django.contrib.contenttypes', 5 'django.contrib.sessions', 6 'django.contrib.messages', 7 'django.contrib.staticfiles', 8 'rest_framework', 9 'corsheaders', 10] 11 12MIDDLEWARE = [ 13 'django.middleware.security.SecurityMiddleware', 14 'django.contrib.sessions.middleware.SessionMiddleware', 15 'django.middleware.common.CommonMiddleware', 16 'django.middleware.csrf.CsrfViewMiddleware', 17 'django.contrib.auth.middleware.AuthenticationMiddleware', 18 'django.contrib.messages.middleware.MessageMiddleware', 19 'django.middleware.clickjacking.XFrameOptionsMiddleware', 20 'corsheaders.middleware.CorsMiddleware', 21 'django.middleware.common.CommonMiddleware', 22] 23 24CORS_ORIGIN_WHITELIST = ( 25 'localhost:8000', 26 '127.0.0.1:8000' 27) 28CORS_ORIGIN_REGEX_WHITELIST = ( 29 'localhost:8000', 30 '127.0.0.1:8000' 31) 32CORS_ORIGIN_ALLOW_ALL = True 33 34REST_FRAMEWORK = { 35 'DEFAULT_RENDERER_CLASSES': ( 36 'rest_framework.renderers.JSONRenderer', 37 ), 38 'DEFAULT_PARSER_CLASSES': ( 39 'rest_framework.parsers.JSONParser', 40 ) 41}

・ajax_test/urls.py

Python

1from django.contrib import admin 2from django.urls import path 3from django.conf.urls import url, include 4from test_dir.urls import router as test_router 5 6urlpatterns = [ 7 path('admin/', admin.site.urls), 8 url(r'^api/', include(test_router.urls)), 9] 10

・test_dir/urls.py

Python

1from rest_framework import routers 2from .views import TestAPIViewSet 3 4router = routers.DefaultRouter() 5router.register(r'test', TestAPIViewSet)

・test_dir/model.py

Python

1from django.db import models 2from rest_framework.views import APIView 3from urllib.parse import urlparse 4import mysql.connector 5from rest_framework.response import Response 6 7class TestAPI(models.Model): 8 id = models.IntegerField('id') 9 name = models.CharField('name',max_length=20) 10 value = models.IntegerField('value') 11 class Meta: 12 app_label = "TestAPI" 13 db_table = "test" 14

・test_dir/serializer.py

Python

1from rest_framework import serializers 2from .models import TestAPI 3 4class TestAPISerializer(serializers.ModelSerializer): 5 class Meta: 6 model = TestAPI 7 fields = ('id', 'name', 'value')

・views.py

Python

1import django_filters 2from rest_framework import viewsets, filters 3 4from .models import TestAPI 5from .serializer import TestAPISerializer 6 7from django.http import JsonResponse 8 9class TestAPIViewSet(viewsets.ModelViewSet): 10 queryset = TestAPI.objects.all() 11 serializer_class = TestAPISerializer 12 base_url = '/api/test/' 13 14def DBDataRes(request): 15 json_ary = [] 16 c = connections['default'] 17 cursor = c.cursor 18 try: 19 cursor.execute('select id, name, value from test') 20 results = cursor.fetchall() 21 for result in results.order_by('id'): 22 dict = OrderedDict( 23 ('id', result.id), 24 ('name', result.name), 25 ('value', result.value) 26 ) 27 json_ary.append(dict) 28 29 c.commit() 30 return JsonResponse(json_ary) 31 except Exception as err: 32 c.rollback() 33 raise err 34 finally: 35 cursor.close() 36 c.close()

・ajaxtest.js

JavaScript

1var ajax_test = function () { 2 alert('start'); 3 $.ajax({ 4 url: 'http://localhost:8000/api/test', 5 type: 'GET', 6 data: { 7 }, 8 dataType: 'jsonp', 9 }) 10 .done(function(data){ 11 data.foreach(function (datum) { 12 $('#ajax_result').append('<div><div><div>id</div><div>' + datum.id + '</div></div><div><div>name</div><div>' + datum.name + '</div></div><div><div>value</div><div>' + datum.value + '</div></div></div>'); 13 }) 14 }) 15 .fail(function(xhr, textStatus, errorThrown){ 16 alert('fail'); 17 }) 18}; 19 20 21//初期処理 22$(function () { 23 document.getElementById('btn_test').addEventListener('click', function () { 24 ajax_test(); 25 }, false); 26});

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

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

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

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

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

guest

回答2

0

自己解決

大変頓珍漢な結果で申し訳ありませんが、
Apache上のajaxtest.htmlから
Apacheとは別に起動していたPython上のREST APIへ接続していたことで発生していたCORSが原因でした。

現時点でajaxtest.htmlとREST APIは別々のサーバにする必要はないので、
ajaxtext.htmlの内容をPython側のテンプレートに移植して、
Python上のWebページからAjaxを実行することで(JavaScript側も一部修正が必要でしたが)REST APIのデータをJavaScriptで受けることが出来ました。

大変失礼致しました。有難うございました。

修正後は以下の通りになります。

・Settings.py

Python

1#ajaxtest.jsなどの固定で読み込むファイルの設置ディレクトリ定義 2STATIC_URL = '/static/' 3STATICFILES_DIRS = ( 4 os.path.join(BASE_DIR, 'static'), 5)

・JavaScriptやCSSを入れるstaticディレクトリ及びtemplatesディレクトリの追加
/
├ajax_test
├test_dir
│└templates
├static
│├scripts
│├css
││

・ajax_test/urls.py

Python

1(省略) 2urlpatterns = [ 3(中略) 4 #test_dir/urls.pyへの参照追加 5 path('test/', include('test_dir.urls')), 6]

・test_dir/urls.py

Python

1(省略) 2from django.urls import path 3from . import views 4(中略) 5#ajaxtest.htmlのWebページ定義追加 6urlpatterns = [ 7 path('testpage/', views.TestPage.as_view(), name='testpage'), 8] 9

・test_dir/views.py

Python

1from django.views import generic 2(中略) 3#ajaxtest.htmlを移植したテンプレートの定義 4class TestPage(generic.TemplateView): 5 template_name = 'ajaxtest.html'

・test_dir/templates/ajaxtest.html

HTML

1{% load staticfiles %} 2<!DOCTYPE html> 3<html> 4<head> 5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 6 <link rel="stylesheet" type="text/css" href="{% static 'css/index.css' %}"> 7 <link rel="stylesheet" type="text/css" href="{% static 'css/jquery-ui.css' %}"> 8 <title>Ajaxのテストページ</title> 9</head> 10<body> 11 <div id="btn_test" class="div_link">データ取得</div> 12 <div>テスト結果</div> 13 <div id="ajax_result"></div> 14 <script type="text/javascript" src="{% static 'scripts/ajaxtest.js' %}"></script> 15 <script type="text/javascript" src="{% static 'scripts/jquery-ui.min.js' %}"></script> 16</body> 17</html>

・static/srcipts/ajaxtest.js

JavaScript

1var ajax_test = function () { 2 //dataTypeの修正 3 $.ajax({ 4 url: 'http://localhost:8000/api/test', 5 type: 'GET', 6 data: { 7 }, 8 dataType: 'json', 9 }) 10 .done(function(data){ 11 alert('done'); 12 console.log(data); 13 //ForEach文の修正 14 for(var n = 0; n < data.length - 1; n++){ 15 var datum = data[n]; 16 $('#ajax_result').append('<div><div><div>id</div><div>' + datum.id + '</div></div><div><div>name</div><div>' + datum.name + '</div></div><div><div>value</div><div>' + datum.value + '</div></div></div>'); 17 } 18 }) 19 .fail(function(xhr, textStatus, errorThrown){ 20 alert('fail'); 21 }) 22}; 23 24$(function () { 25 document.getElementById('btn_test').addEventListener('click', function () { 26 ajax_test(); 27 }, false); 28});

投稿2018/05/16 06:37

shimeji_forest

総合スコア6

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

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

0

JSON を確実に返しているのであればバックエンドの Python は特に精査する必要はないと思います。
むしろ、その JSON と JavaScript の挙動が気になるので、DOM操作をしている以下の部分を

js

1.done(function(data){ 2 console.log(data); // <- 追加 3 data.foreach(function (datum) { 4 $('#ajax_result').append('<div><div><div>id</div><div>' + datum.id + '</div></div><div><div>name</div><div>' + datum.name + '</div></div><div><div>value</div><div>' + datum.value + '</div></div></div>'); 5 }) 6})

のようにして表示された JSON を見せてもらえないでしょうか。

ちなみに jQuery は久しく使っていないのですが、 JSON が返ってくるのであれば ajax の dataType: json が正しいのではないでしょうか。

投稿2018/05/15 09:24

og24715

総合スコア832

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

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

shimeji_forest

2018/05/16 06:42

実はconsole.log(data);を埋め込んでも.done()へ辿り着く前にエラーが発生していた為、JavaScript側ではJSONを確認出来ない状態でした。 ちなみに、REST APIで取得した場合、 [{"id":1,"name":"あ","value":100},{"id":2,"name":"い","value":-50},{"id":3,"name":"う","value":20}] と返って来る様になっていました。 ajaxはご指摘頂いた通りで、dataType: jsonが正しかったです。有難うございました。
og24715

2018/05/16 06:56

CORS が原因でリクエスト失敗しているのであれば 4xx 系のレスポンスが返りそうですけど不思議ですね
shimeji_forest

2018/05/17 06:31

私自身理解不足であるということで申し訳ない面があるのですが、調べ直すとCORSの問題という認識が誤りであり、サーバ側でレスポンスヘッダにクロスドメイン要求を許可する設定が必要なのに現時点で入れていないことが本当の原因の様な気がしてきました。 ajaxのdataTypeをjsonに修正した状態でHTTPステータスコードを確認してみましたが、この場合は301 Moved Permanentlyが返って来ていて、 コンソール上では以下の様に表示されていました。 Failed to load http://localhost:8000/api/test: Redirect from 'http://localhost:8000/api/test' to 'http://localhost:8000/api/test/' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access. 今は自分の環境内でAjaxを用いたREST APIのテストを行うことが目的だったので自己解決時のソースでも問題ないのかもしれませんが、もしかしたらviewsの一部を response = HttpResponse(json_ary, content_type="application/json") response["Access-Control-Allow-Origin"] = "*" return response という感じへ書き替えるべきかもしれません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問