「tabulatorを使って、データベースの更新にトライ」を年初に投稿して、久々にDEMOサイトにアクセスしてみたら、動かなくなっていました。そこで最近はpythonでプロトタイプシステムを作成していたので、そちらで再掲します。クライアントの作りはjssp-rpcをajaxに書き換えただけです。Python、Flaskについてはいろいろ紹介されているので、ここでは触れません。
ローカル環境
- Windows-x86Windows10HOME
- Anaconda3-5.2.0 ライブラリは以下を利用
- Flask
- SQLite
- クライアントライブラリ tabulator
wwwroot
|-main.py
|-test.db
|-templatesフォルダにhtmlを配置
|-staticフォルダにCDNで取得できないライブラリを配置
公開環境
こちらで紹介している拡張したpythonにライブラリを追加する方法で再構築しました。
Azureで動作させるにあったっては、結構苦労しました。ローカルで仮想環境(env)で動作させてgitでアップする例がMSのサイトでも紹介されていますが、site-packagesのライブラリを読み込めず動かす事ができませんでした。
そこで、D:\home\site\wwwroot配下にフォルダを作成し、そこにsite-packagesをftpでアップロードし、プログラムにsys.path.append('D:/home/site/wwwroot/Lib/site-packages')でロード場所を追加してライブラリを読み込むようにしました。Anacondaのsite-packagesは量が多いので、Azure WebAppsのバージョンと同じ3.4のpythonのsite-packagesにFlaskをpipで追加したものをアップしています。
###demo→2 4行目の2「Tablatorを使ってDBのグリッド表示、登録を行う」
※7/12環境設定を拡張してライブラリを追加する方法で環境を再構築
メニューよりTablatorを使ってDBのグリッド表示、登録を行うをクリック。
表示するのはLoad、追加の場合はadd-rowで新規行を表示し入力してExcute、修正・削除は右端をupd/delを選択してExcute。
ソース
{% extends "base.html" %}
{% block body %}
<div class="card" ; >
<div class="card-header" style="height:50px; font-size:1.5rem; ">
<b>Tablatorを使ってDBのグリッド表示、登録を行う</b>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-2 mb-1">
<input type="text" class="form-control" id="input-text" value="%">
</div>
<div class="col-md-2 mb-1">
<button class="btn btn-default" id="button" style="width: 100px; padding: 5px;">Load Data</button>
</div>
<div class="col-md-2 mb-1">市Autocomplete</div>
<div class="col-md-2 mb-1">
<input type="text" class="form-control" id="tags">
</div>
<div class="col-md-2 mb-1">
<button class="btn btn-default" id="excute_button" style="width: 100px; padding: 5px;">Excute</button>
</div>
<div class="col-md-2 mb-1">
<button class="btn btn-default" id="add-row" style="width: 100px; padding: 5px;">Add-row</button>
</div>
</div>
</div> <!--class="card-body"の終端-->
</div> <!--class="card"の終端-->
<div id="example-table"></div>
<script type="text/javascript">
"use strict";
// **********************************************
// autoコンプリート
// **********************************************
$(function() {
$("#tags").autocomplete({
source: function(request, response) {
$.ajax({
url: "/city",
dataType: "json",
type: "POST",
cache: false,
data: { param: request.term },
success: function(data) {
response(JSON.parse(data.city));
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
response(['']);
}
});
}
});
});
// **********************************************
//
// **********************************************
$("#example-table").tabulator({
height:400, // set height of table (in CSS or here), this enables the Virtual DOM and improves render speed dramatically (can be any valid css height value)
layout:"fitColumns", //fit columns to width of table (optional)
pagination:"local",
paginationSize:10,
columns:[ //Define Table Columns
{title:"Id", field:"id", width:60},
{title:"Name", field:"name", editor:"input", width:150},
{title:"Age", field:"age", editor:"input", width:80},
{title:"Adress", field:"adress", editor:"input", width:150},
{title:"Code", field:"code", editor:"input", width:80},
{title:"Date Of Birth", field:"dob", editor:"input", width:80},
{title:"Male/Female", field:"mf",editor:"select", editorParams:{"male":"Male", "female":"Female"}, width:80},
{title:"Upd/Del", field:"ud",editor:"select", editorParams:{"":"", "Add":"Add","Upd":"Upd", "Del":"Del"}, width:80},
],
});
//新規行追加
$("#add-row").click(function(){
$("#example-table").tabulator("addRow", {ud:"Add"});
});
$(window).load(init());
function init() {
//ロード
$("#button").click(function() {
var textData = JSON.stringify({"text":$("#input-text").val()});
$.ajax({
type:'POST',
url:'/tabPost',
data:textData,
contentType:'application/json',
success:function(data) {
var tabledata = JSON.parse(data.ResultSet);
$("#example-table").tabulator("setData",tabledata );
}
});
return false;
});
//実行
$("#excute_button").click(function() {
var data = $("#example-table").tabulator("getData");
for(var i = 0; i < data.length; i++) {
switch( data[i].ud ){
case 'Add':
var textData = JSON.stringify({"add_name":data[i].name,
"add_age":data[i].age,
"add_adress":data[i].adress,
"add_code":data[i].code,});
$.ajax({
type:'POST',
url:'/tabAdd',
data:textData,
contentType:'application/json',
success:function(data) {
alert("登録結果=" + data);
}
});
break;
case 'Upd':
alert("★Upd");
var textData = JSON.stringify({"id":data[i].id,
"add_name":data[i].name,
"add_age":data[i].age,
"add_adress":data[i].adress,
"add_code":data[i].code,});
$.ajax({
type:'POST',
url:'/tabUpd',
data:textData,
contentType:'application/json',
success:function(data) {
alert("更新結果=" + data);
}
});
break;
case 'Del':
alert("★Upd");
var textData = JSON.stringify({"id":data[i].id})
$.ajax({
type:'POST',
url:'/tabDel',
data:textData,
contentType:'application/json',
success:function(data) {
alert("削除結果=" + data);
}
});
break;
default:
break;
}
}
return false;
});
}
</script>
{% endblock %}
#**************************************
# プロト
#**************************************
import os
import sys
import platform
import sqlite3
#sys.path.append('D:/home/site/wwwroot/Lib/site-packages') ←不要になりました。
from flask import Flask, render_template, request, jsonify, send_file, make_response, send_from_directory, request, jsonify, session, redirect, url_for
import json
import werkzeug
import datetime
#import openpyxl
#import pyodbc
#from ldap3 import Server, Connection
sqlite_DB = './test.db'
application = Flask(__name__)
application.config.from_object(__name__)
#**************************************
# 共通処理:SQLiteの戻り値が単純な配列なのでそれを辞書型にする定義
#**************************************
def dict_factory(cursor, row):
d = {}
for idx, col in enumerate(cursor.description):
d[col[0]] = row[idx]
return d
#**************************************
# オートコンプリート
#**************************************
@application.route("/city",methods=['POST'])
def city_tags():
result = []
db_key = [request.form['param'] + "%"]
connection = sqlite3.connect(sqlite_DB)
cursor = connection.cursor()
for row in cursor.execute('select city_name from city where city_name like ?',db_key):
result.append(row[0])
print(row[0])
cursor.close()
connection.close()
return jsonify(city = json.dumps(result))
#**************************************
# ルーティング
#**************************************
#初期メニュー
@application.route('/')
def index():
return render_template('index.html',msg='login')
@application.route('/test', methods=['POST'])
def test():
return render_template('TEST.html')
#tabltorグリッド
@application.route('/tabDB',methods=['POST'])
def tabDB():
return render_template('tabDB.html')
#Bootstrap画面装飾
@application.route('/Bootstrap',methods=['POST'])
def Bootstrap():
try:
if request.form['name'] == "": #値が空文字の場合
key = "%"
else: #値がセットされている場合
key = request.form['name'] + "%"
except:
key = "%" #例外処理 他の画面から呼ばれた場合
db_key = [key] #配列にして渡している
connection = sqlite3.connect(sqlite_DB)
connection.row_factory = dict_factory
cursor = connection.cursor()
cursor.execute('select * from test where name like ?',db_key)
result = cursor.fetchall()
cursor.close()
connection.close()
return render_template('Bootstrap.html',result=result)
#**************************************
#tabltorのデータ取得
#**************************************
@application.route('/tabPost', methods=['POST'])
def lower_conversion():
text = request.json['text']
connection = sqlite3.connect(sqlite_DB)
connection.row_factory = dict_factory
cursor = connection.cursor()
key = [text] #配列にして渡している
cursor.execute('select * from test where code like ?',key)
result = cursor.fetchall()
cursor.close()
connection.close()
return jsonify(ResultSet=json.dumps(result)) #json.dumpsで辞書型をjson形式に変換した上で、
#jsonifyでResultSet=〇〇→ResultSet:〇〇に変換している。Content-Typeをapplication/json に設定して Response を返してくれる。
#**************************************
#tabltorの登録
#**************************************
@application.route('/tabAdd', methods=['POST'])
def tabAdd():
connection = sqlite3.connect(sqlite_DB)
data = [None,request.json['add_name'],int(request.json['add_age']),request.json['add_adress'],request.json['add_code'],'','']
try:
connection.execute('INSERT INTO test VALUES (?, ?, ?, ?, ?, ?, ?)', data)
connection.commit()
connection.close()
return "success"
except sqlite3.Error as e:
print('sqlite3.Error occurred:', e.args[0])
connection.close()
return "error" + e.args[0]
#**************************************
#tabltorの更新
#**************************************
@application.route('/tabUpd', methods=['POST'])
def tabUpd():
connection = sqlite3.connect(sqlite_DB)
data = [request.json['add_name'],
int(request.json['add_age']),
request.json['add_adress'],
request.json['add_code'],'','',
request.json['id']]
try:
connection.execute('update test set name = ?, age = ?, adress = ?, code = ?, dateofbirth = ?, male_female = ? where id =?', data)
connection.commit()
connection.close()
return "success"
except sqlite3.Error as e:
print('sqlite3.Error occurred:', e.args[0])
connection.close()
return "error" + e.args[0]
#**************************************
#tabltorの削除
#**************************************
@application.route('/tabDel', methods=['POST'])
def tabDel():
connection = sqlite3.connect(sqlite_DB)
data = [request.json['id']]
try:
connection.execute('DELETE FROM test where id =?', data)
connection.commit()
connection.close()
return "success"
except sqlite3.Error as e:
print('sqlite3.Error occurred:', e.args[0])
connection.close()
return "error" + e.args[0]
#**************************************
# テストサーバ起動
#**************************************
if __name__ == '__main__':
application.debug = True # デバッグ
application.run(host='0.0.0.0', port=8000)```
CREATE TABLE test (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name text DEFAULT '',
age integer DEFAULT zero,
adress text DEFAULT '',
code text DEFAULT '',
dateofbirth text DEFAULT '',
male_female text DEFAULT ''
);
web.config、base.html、common.pyはこちらをご覧ください。
とりあえずTablatorでDBアクセスをやろうとしている方のご参考に取り急ぎ再掲します。
時間を見つけて他のプログラムを紹介できればと考えています。