BETA

【Python】FullCalendarとMySQLを連携して予定を登録できるようにする

投稿日:2019-01-09
最終更新:2019-01-09
※この記事は外部サイト(https://www.doraxdora.com/blog/2018/06/19/...)からのクロス投稿です

おはようございます。

引き続き FullCalendar。
今回は MySQLにテーブルを作成してカレンダーに表示するデータを登録できるところまでやってみました。

プログラムは前回のものを流用。

【Python】FullCalendar を使ったWEBページを作ってみる

MySQLの準備

MySQLのインストール


MySQL(フリーのMariaDBを使います)のインストールは次の記事を参照していただければ。

MariaDB 10.2.6 のインストールからテーブル作成まで

テーブルの作成

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');

画面の修正


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 なんかを使ってもう少し詳細な予定を登録できるようにしたり、
登録済みの予定を更新、削除までできたらいいかなと思います。

ではでは。

 

技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

@doraxdoraの技術ブログ 主に Java, C#, Python, Javascript の記事を載せていく予定。

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる
技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
or 外部アカウントではじめる
10秒で技術ブログが作れます!