5
8

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.

tabulatorを使って、データベースの更新にトライ(python版)

Last updated at Posted at 2018-10-18

「tabulatorを使って、データベースの更新にトライ」を年初に投稿して、久々にDEMOサイトにアクセスしてみたら、動かなくなっていました。そこで最近はpythonでプロトタイプシステムを作成していたので、そちらで再掲します。クライアントの作りはjssp-rpcをajaxに書き換えただけです。Python、Flaskについてはいろいろ紹介されているので、ここでは触れません。

ローカル環境

  1. Windows-x86Windows10HOME
  2. Anaconda3-5.2.0 ライブラリは以下を利用
  3. Flask
  4. SQLite
  5. クライアントライブラリ 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。

ソース

tabDB.html
{% 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 %}
main.py
#**************************************
# プロト
#**************************************
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)```
クリエイトsql
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アクセスをやろうとしている方のご参考に取り急ぎ再掲します。
時間を見つけて他のプログラムを紹介できればと考えています。

5
8
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
5
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?