1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

APIサーバーをHTMLからJSONでAjax通信するまでの手順

Posted at

はじめに

前回の記事で、KaggleのHouse Sales in King County, USAのデータセットを使って、XGboost機械学習で学習モデルを生成して、その学習モデルをFlaskでAPIサーバーにするというのをやりました。今回は、そのAPIサーバー使って、HTMLからJSONでAjax通信するまでの手順を説明しています。機械学習で学習したモデルをAPIサーバーにするまでの手順は以下の記事を参考にしてみてください。

KaggleのHouse Sales in King County, USAのデータセットを使って、機械学習を行い、APIサーバーにするまでの手順

Ajax通信

ここでは、HTMLからjavascriptのAjaxで通信できるようにするために、Flaskで書いた、APIサーバーの起動ファイルを以下のように追記する必要があります。追記するのは、flask_corsというライブラリとそれに関連するコードです。flask_corsは事前にインストールしてある必要があります。

housesails_app.py
import json

from flask import Flask
from flask import request
from flask import abort
from flask_httpauth import HTTPBasicAuth
from flask_cors import CORS #追加する

import pandas as pd
from sklearn.externals import joblib
import xgboost as xgb

model = joblib.load("house_sales_model.pkl")

app = Flask(__name__)

# 追加
@app.after_request
def after_request(response):
  response.headers.add('Access-Control-Allow-Origin', '*')
  response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization')
  response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS')
  return response
# ↑ここまでを追加

# BasicAuth
auth = HTTPBasicAuth()

users = {
    "username1": "password1",
    "username2": "password2"
}

@auth.get_password
def get_pw(username):
    if username in users:
        return users.get(username)
    return None

# Get headers for payload
headers = ['sqft_living','sqft_above','sqft_basement','lat','long','sqft_living15','grade_3','grade_4','grade_5','grade_6','grade_7','grade_8','grade_9','grade_10','grade_11','grade_12']

@app.route('/house_sails', methods=['POST'])

# BasicAuth
@auth.login_required

def housesails():
    if not request.json:
        abort(400)
    payload = request.json['data']
    values = [float(i) for i in payload.split(',')]
    data1 = pd.DataFrame([values], columns=headers, dtype=float)
    predict = model.predict(xgb.DMatrix(data1))
    return json.dumps(str(predict[0]))


if __name__ == "__main__":
    app.run(debug=True, port=5000)

HTMLからPOSTをしてJSONデータをAPIサーバーに送信する

HTMLファイルは、インターフェイスの部分はタグ内のinputタグなどで、データの入力フォームを作ります。その入力データをjavascriptで受け取って、整形し、JSON形式に変換して、Ajax通信でPOSTしています。通信が成功したら、APIサーバーからの予測値を受け取り、それをtextareaタグのエリア内に表示するという処理をしています。

index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>HTMLファイルからPOSTでJSONデータを送信する</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
</head>
<body>
    <div class="container">
    <h1>HTMLファイルからPOSTでJSONデータを送信する</h1>
    <div class="alert alert-primary" role="alert">
    <p>URL: <input type="text" id="url_post" name="url" class="form-control" size="100" value="http://localhost:5000/house_sails"></p>
    </div>
    <div class="d-flex bd-highlight">
    <div class="flex-fill bd-highlight alert alert-primary mr-3" role="alert">
    <p>sqft_living: <input type="number" id="value1" class="form-control" size="30" value=-1.026685></p>
    </div>

    <div class="flex-fill bd-highlight alert alert-primary mr-3" role="alert">
    <p>sqft_above: <input type="number" id="value2" class="form-control" size="30" value=-0.725963></p>
    </div>

    <div class="flex-fill bd-highlight alert alert-primary" role="alert">
    <p>sqft_basement: <input type="number" id="value3" class="form-control" size="30" value=-0.652987></p>
    </div>
    </div>

    <div class="d-flex bd-highlight">
    <div class="flex-fill bd-highlight alert alert-primary mr-3" role="alert">
    <p>lat: <input type="number" id="value4" class="form-control" size="30" value=-0.323607></p>
    </div>

    <div class="flex-fill bd-highlight alert alert-primary mr-3" role="alert">
    <p>long: <input type="number" id="value5" class="form-control" size="30" value=-0.307144></p>
    </div>

    <div class="flex-fill bd-highlight alert alert-primary" role="alert">
    <p>sqft_living15: <input type="number" id="value6" class="form-control" size="30" value=-0.946801></p>
    </div>
    </div>

    <div class="alert alert-primary" role="alert">
    <p>gradeを選択:
    <select name="grade" id="grade" class="form-control form-control-lg">
        <option value="grade1">grade1</option>
        <option value="grade2">grade2</option>
        <option value="grade3">grade3</option>
        <option value="grade4">grade4</option>
        <option value="grade5">grade5</option>
        <option value="grade6">grade6</option>
        <option value="grade7">grade7</option>
        <option value="grade8">grade8</option>
        <option value="grade9">grade9</option>
        <option value="grade10">grade10</option>
        <option value="grade11">grade11</option>
        <option value="grade12">grade12</option>
      </select>
    </p>
    </div>
    
    <p>usename: <input type="text" name="username" id="username" class="form-control" value="bitstudio"/></p>
    <p>password: <input type="password" name="password" id="password" class="form-control" value="hirayama"/></p>
    <p><button id="button" type="button" class="btn btn-primary">submit</button></p>
    <textarea id="response" class="form-control" cols=120 rows=4 disabled></textarea>
    <p><p>
</div>

</body>

<script type="text/javascript">

$(function(){

    $("#response").html("Response Values");

    $("#button").click( function(){
        let value07 = 0;
        let value08 = 0;
        let value09 = 0;
        let value10 = 0;
        let value11 = 0;
        let value12 = 0;
        let value13 = 0;
        let value14 = 0;
        let value15 = 0;
        let value16 = 0;
        let element = document.getElementById("grade");
        let grade01 = element.value;
        if (grade01 == "grade1") {
        value07 = 0;
        }else if (grade01 == "grade2") {
            value07 = 0;
        }else if (grade01 == "grade3") {
            value07 = 1;
        }else if (grade01 == "grade4") {
            value08 = 1;
        }else if (grade01 == "grade5") {
            value09 = 1;
        }else if (grade01 == "grade6") {
            value10 = 1;
        }else if (grade01 == "grade7") {
            value11 = 1;
        }else if (grade01 == "grade8") {
            value12 = 1;
        }else if (grade01 == "grade9") {
            value13 = 1;
        }else if (grade01 == "grade10") {
            value14 = 1;
        }else if (grade01 == "grade11") {
            value15 = 1;
        }else{
            value16 = 1;
        }
        var url = $("#url_post").val();
        var feature1 =
            $("#value1").val() + "," +
            $("#value2").val() + "," +
            $("#value3").val() + "," +
            $("#value4").val() + "," +
            $("#value5").val() + "," +
            $("#value6").val() + "," +
            value07 + "," +
            value08 + "," +
            value09 + "," +
            value10 + "," +
            value11 + "," +
            value12 + "," +
            value13 + "," +
            value14 + "," +
            value15 + "," +
            value16;

        var JSONdata = {
                data: feature1
            };

        alert(JSON.stringify(JSONdata));

        var username = $("input#username").val();
        var password = $("input#password").val();

        $.ajax({
            type: 'POST',
            url: url,
            //basic認証送信
            beforeSend: function(xhr){
            xhr.setRequestHeader('Authorization', 'Basic ' + btoa(username+':'+password));},
            data: JSON.stringify(JSONdata),
            contentType: 'application/JSON',
            dataType: 'JSON',
            scriptCharset: 'utf-8',
            success : function(data) {

                // Success
                alert("success");
                alert(JSON.stringify(JSONdata));
                $("#response").html(JSON.stringify(data));
            },
            error : function(data) {

                // Error
                alert("error");
                alert(JSON.stringify(JSONdata));
                $("#response").html(JSON.stringify(data));
            }
        });
    })
})
</script>

</html>
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?