form内のinputタグ全てをjsonにして...
POSTは、formデータをサーバへ送信する際に活用するタグで、その中のinputタグに含まれるデータをサーバ側で受け取るのは、特に面倒だったりもする...
例えば、<input type="text" name="id" id="id">
とか、<input type="text" name="id" id="name">
とか...紛らわしい上に扱いづらい、そしてサーバ側の言語には予約されていたりするので、さらに変数名を安易に考えられたものについては面倒...
そこで単純に、jsonデータにして受け渡し、サーバ側でも受け取りをjson形式にする事で、加工や挿入、代入などが可能になり、処理もフロント側だけでほぼ完結したりもできる。
準備するもの
サーバサイド
- Python3.6<=x
- Tinydb
- bottle
フロントエンド
- javascript
- html
- Chrome
実際のコード
実際と言いつつも、実行はしていないwけど、多分、動く...
※コメント頂ければ、修正します。
これらは、ただ抜粋しただけだから動かない可能性もあるが、
ポイントを押さえておけば問題ないはず...
まずは、js側から...その次に、サーバ側の処理について...説明したいと思う。
import bottle
from bottle import request
from tinydb import TinyDB as tydb
@route("/")
def index():
index = """
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Post 2 Json</title>
</head>
<body>
<form action="/db" method="POST" id="form_cnts" name="form_cnts" enctype="multipart/form-data">
USER: <input type="text" name="user" id="user">
<br>
PASSWORD: <input type="text" name="paswd" id="paswd">
<input type="hidden" name="secret_key" id="secret_key" value="b42c66d06dc047e191aab859429a0105">
</form>
<script>
/*---------------------------------------------------- $ ---------------------------------------------------------------*/
/** ID と Classを変換する関数
* $('#id')
* @param {String} - let id_name = $('#id')
* @return {Object} - id-tag
*/
if (String.prototype.$ == undefined){
$ = (x) => {
const idn = /^#/g
if (typeof x == "string") {
if(x.match(idn)) return document.getElementById(x.replace(idn, ""))
}
return x
}
}
let PostDB = (e) => {
e.preventDefault()
let JD = {}
let FORMCNTS = $("#form_cnts")
let INPUT_DATA = document.getElementsByTagName('input')
for(let d of Object.values(INPUT_DATA)){JD[d.name]=d.value}
let JSON_DATA = '['+JSON.stringify(JD).toString()+']'
let CUSTOM_HEADER = "CUSTOM-HEADER-NAME"
let customHeaders = new Headers({'Content-Type': 'application/json','X-
Custom-Header': CUSTOM_HEADER })
let customInit = { method: 'POST',
headers: customHeaders,
Accept: 'application/json',
mode: 'cors',
cache: 'default',
credentials: 'same-origin',
body: JSON.stringify(JSON_DATA)}
let url = FORMCNTS.action
let customRequest = new Request(url, customInit)
fetch(customRequest)
.then((response) => {
return response.json()
})
.then((resp) => {
if(resp.status == "OK") {
for(let d of Object.values(INPUT_DATA)){d.value=""}
let fade_div = $("#fade_div")
fade_div.innerText = resp.status
fadeIn(fade_div,1500,function(){
fadeOut(fade_div,1500,function(){
})
})
}
})
.catch(function(error) { console.log(error) })
}
</script>
</body>
</html>
"""
return index
@post('/db')
def do_db():
TYDB = f'{TMP_PATH}/{DATABASE["NAME"]}.json'
_status = "NG"
json_data = {"status": _status}
if request.json != "":
with tydb(TYDB) as db:
json_data = json.loads(request.json)
db.insert(json_data[0])
_status = "OK"
try:
reurl = json_data
request_data = {
"headers":request.headers['Content-Type'],
"json": json_data,
"MEMFILE_MAX":request.MEMFILE_MAX,
"remote_route":request.remote_route,
"is_xhr":request.is_xhr,
"remote_addr":request.remote_addr,
"url":request.url,
"method":request.method,
"status":_status,
"User_Agent":request.get_header('User-Agent')}
response.content_type = 'application/json'
r = HTTPResponse(status=302)
r.set_header('Location', reurl)
return dumps(request_data, ensure_ascii=False, indent=2)
except:
abort(500)
if __name__ == "__main__":
bottle.run(host='0.0.0.0', port=8080)
と、実行されれば、form内のデータがデータベースに登録されるだろう...
まずは、jsの説明から...
ここが重要で、TagName=input
を全て、INPUT_DATA
へ格納する。
その後、for文
で全て抜き出す。その際、name(key)とvalueで紐付けしながら格納する。
もしかすると、もっといい方法があるだろう...
...
let INPUT_DATA = document.getElementsByTagName('input')
for(let d of Object.values(INPUT_DATA)){JD[d.name]=d.value}
...
その後、一度連想配列にする。
何故か?は、サーバ側の処理を確認するといいだろう。
日本語などがあると通常通り引き渡せない事があったので、救済処置として、このような形にしてみた。
let JSON_DATA = '['+JSON.stringify(JD).toString()+']'
あとは、非同期処理のfetch
を使ってPOSTすればいい。
その時重要になるのが、Content-Type
だ。これをjsonにしておかないと、受け渡しの際に、サーバ側で処理が複雑になってしまう。
... customHeaders = new Headers({'Content-Type': 'application/json',...
最後となるが、サーバ側の処理をみてみよう。
...json.loads(request.json)
...db.insert(json_data[0])
と、上記のようにjson形式で呼び出した上で、データベースへ格納する際には、連想配列にて、[0]
とし引き渡す事で、str処理などを気にせず、格納できる。
色々試したのだが、連想配列以外での受け渡しだとうまく受け取れないdict
だったり、str
だったり...typeが異なり、受け取りの処理が複雑かつ、面倒になりがちだった...
ひとまず、これで落ち着くと思う。
以上。