【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 なんかを使ってもう少し詳細な予定を登録できるようにしたり、
登録済みの予定を更新、削除までできたらいいかなと思います。
ではでは。
ディスカッション
コメント一覧
まだ、コメントがありません