【Python】FullCalendarとMySQLを連携して予定を登録できるようにする
おはようございます。
昨日に引き続き FullCalendar。
今回は MySQLにテーブルを作成してカレンダーに表示するデータを登録できるところまでやってみました。
プログラムは前回のものを流用。
スポンサーリンク
目次
下準備
MySQLのインストール
MySQL(フリーのMariaDBを使います)のインストールは次の記事を参照していただければ。
テーブルの作成
CREATE TABLE IF NOT EXISTS TBL_SCHEDULE (
USER_CD VARCHAR(10)
, ID INT(10)
, TITLE VARCHAR(100)
, START DATETIME
, END DATETIME
, TEXTCOLOR VARCHAR(20)
, COLOR VARCHAR(20)
, URL VARCHAR(100)
, ALLDAY VARCHAR(10)
, PRIMARY KEY(USER_CD, ID)
)データ登録
ひとまずサンプルのデータを登録しておきます。
DELETE FROM TBL_SCHEDULE;
INSERT INTO TBL_SCHEDULE VALUES('001','1','定例会','2018-06-06T19:00:00','2018-06-06T21:00:00','','','', 'FALSE');
INSERT INTO TBL_SCHEDULE VALUES('001','2','外出','2018-06-18T14:00:00','2018-06-18T17:30:00','','','', 'FALSE');
INSERT INTO TBL_SCHEDULE VALUES('001','3','有給','2018-06-28','2018-06-28','','','', 'TRUE');
ライブラリの追加
次のライブラリを「メニュー」>「Default Settings」よりインストールします。
- mysql-connector-python-rf
画面の修正
fullCalendar のオプションで時刻の形式を指定するようにしたのと、
予定を入力した際にサーバーのメソッドを呼び出してデータ登録するようにしました。
index.html
<!DOCTYPE html>
<html>
<head>
<title>カレンダーサンプル</title>
<link rel="stylesheet" href="{{ static_url('css/fullcalendar.min.css') }}"/>
<link rel="stylesheet" href="{{ static_url('css/style.css') }}"/>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="{{ static_url('js/moment.min.js') }}"></script>
<script type="text/javascript" src="{{ static_url('js/fullcalendar.min.js') }}"></script>
<script type="text/javascript" src="{{ static_url('lang/ja.js') }}"></script>
<script>
// ページ読み込み時の処理
$(document).ready(function () {
// カレンダーの設定
$('#calendar').fullCalendar({
height: 550,
lang: "ja",
header: {
left: 'prev,next today',
center: 'title',
right: 'month,basicWeek,basicDay'
},
timeFormat: 'HH:mm',
selectable: true,
selectHelper: true,
navLinks: true,
eventSources: [{
url: 'http://localhost:8080/getCalendar',
dataType: 'json',
async: false,
type : 'GET',
error: function() {
$('#script-warning').show();
}
}],
select: function(start, end, resource) {
var title = prompt("予定タイトル:");
var eventData;
if (title) {
eventData = {
title: title,
start: start,
end: end,
allDay: true
};
$('#calendar').fullCalendar('renderEvent', eventData, true);
$.ajax({
url: "http://localhost:8080/regist",
type: "POST",
data: JSON.stringify(eventData),
success: function(jsonResponse) {
alert("予定を登録しました。")
},
error: function() {
}
});
}
$('#calendar').fullCalendar('unselect');
},
editable: true,
eventLimit: true,
});
});
</script>
</head>
<body>
<div id='calendar'></div>
</body>
</html>
サーバープログラムの修正
新規クラス追加
MySQL用クラスを追加
MySQLUtil.py
import mysql.connector
import logging
from contextlib import closing
class MySQLUtil:
"""
MySQL 操作用クラス
"""
def __init__(self, host="localhost", port="3306", user="USER01", password="USER01", database="DB01"):
self.config = {
"host": host,
"port": port,
"user": user,
"password": password,
"database": database
}
self.create_db()
def create_db(self):
"""
データベース、及び必要なテーブルを作成します.
:return:
"""
with closing(mysql.connector.connect(**self.config)) as conn:
c = conn.cursor()
# スケジュールテーブル
sql = "CREATE TABLE IF NOT EXISTS TBL_SCHEDULE ("
sql += " USER_CD VARCHAR(10)"
sql += ", ID VARCHAR(10)"
sql += ", TITLE VARCHAR(100)"
sql += ", START DATETIME"
sql += ", END DATETIME"
sql += ", TEXTCOLOR VARCHAR(20)"
sql += ", COLOR VARCHAR(20)"
sql += ", URL VARCHAR(100)"
sql += ", ALLDAY VARCHAR(20)"
sql += ", PRIMARY KEY(USER_CD, ID)"
sql += ")"
c.execute(sql)
c.close()
conn.commit()
def delete_data(self):
"""
データを削除します
:return:
"""
logging.info("delete_data")
with closing(mysql.connector.connect(**self.config)) as conn:
c = conn.cursor()
# データクリア
sql = "DELETE FROM TBL_SCHEDULE"
c.execute(sql)
c.close()
conn.commit()
def insert_data(self, data):
"""
データを登録します
:param ticker:
:return:
"""
with closing(mysql.connector.connect(**self.config)) as conn:
c = conn.cursor()
# データ登録
sql = "INSERT INTO TBL_SCHEDULE VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s)"
c.execute(sql, data)
c.close()
conn.commit()
def get_schedule(self, year_month, user_cd=""):
"""
データ(テーブル)をデータフレームに変換してかえします
:return:
"""
result = []
with closing(mysql.connector.connect(**self.config)) as conn:
c = conn.cursor(dictionary=True)
sql = "SELECT * FROM TBL_SCHEDULE"
sql += " WHERE (DATE_FORMAT(START, '%Y%m') = '" + year_month + "'"
sql += " OR DATE_FORMAT(END, '%Y%m') = '" + year_month + "')"
if user_cd != "":
sql += " AND USER = '" + user_cd + "'"
sql += " ORDER BY USER_CD, ID"
c.execute(sql)
for r in c.fetchall():
result.append({
"user_cd": r['USER_CD'],
"id": r['ID'],
"title": r['TITLE'],
"start": r['START'],
"end": r['END'],
"textColor": r['TEXTCOLOR'],
"color": r['COLOR'],
"url": r['URL'],
"allDay": (r['ALLDAY'] == 'TRUE')
})
return result
def get_next_id(self, user_cd=""):
"""
データ(テーブル)をデータフレームに変換してかえします
:return:
"""
result = 0
with closing(mysql.connector.connect(**self.config)) as conn:
c = conn.cursor(dictionary=True)
sql = "SELECT MAX(ID) + 1 AS ID FROM TBL_SCHEDULE WHERE USER_CD = '" + user_cd + "'"
c.execute(sql)
result = c.fetchone()
return result[r"ID"]URLハンドラー、新規メソッドを追加
Main.py
import json
import logging
import os
import tornado.ioloop
from tornado.web import RequestHandler
from tornado.options import options
from Utils.MySQLUtil import MySQLUtil
from datetime import datetime
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.render("index.html")
class GetCalendar(RequestHandler):
"""
カレンダー取得
"""
def initialize(self):
logging.info("GetCalendar [initialize]")
def get(self):
logging.info("GetCalendar [get]")
mysql = MySQLUtil()
data = mysql.get_schedule("201806", "")
self.write(json.dumps(data, default=support_datetime_default))
class RegistSchedule(RequestHandler):
"""
スケジュール登録
"""
def initialize(self):
logging.info("RegistSchedule [initialize]")
def post(self):
logging.info("RegistSchedule [post]")
mysql = MySQLUtil()
param = json.loads(self.request.body)
allday = "TRUE" if param["allDay"] else "FALSE"
id = mysql.get_next_id('001')
data = [
"001",
id,
param["title"],
param["start"],
param["end"],
"",
"",
"",
allday
]
mysql.insert_data(data)
def support_datetime_default(o):
if isinstance(o, datetime):
return o.isoformat()
raise TypeError(repr(o) + " is not JSON serializable")
app = tornado.web.Application([
(r"/", MainHandler),
(r"/getCalendar", GetCalendar),
(r"/regist", RegistSchedule),
],
template_path=os.path.join(os.getcwd(), "templates"),
static_path=os.path.join(os.getcwd(), "static"),
)
if __name__ == "__main__":
options.parse_command_line()
app.listen(8080)
logging.info("server started")
tornado.ioloop.IOLoop.instance().start()起動してみる
まとめ
なかなか形になってきましたね。
次回は Bootstrap なんかを使ってもう少し詳細な予定を登録できるようにしたり、
登録済みの予定を更新、削除までできたらいいかなと思います。
ではでは。
ディスカッション
コメント一覧
まだ、コメントがありません