Global lo0

One good turn deserves another. GPS×ImageProcess×...

peewee で 秒以下の精度の MySQL DateTime型 カラムを作る

peewee で 秒以下の精度の MySQL DateTime型 カラムを作る

f:id:kuri_megane:20180923170121p:plain

peewee とは pythonORマッパー のひとつです.


ざっくりまとめると...

  • peewee を使って秒以下の値を含むカラムは作れない
  • どうしても peewee を使いたいときは自分でフィールドを定義する
  • そうでなければ別の手段を使う(直接SQL叩くなど)

目次


前提

作りたいテーブル

+----+----------------------------+
| id | rectime                    |
+----+----------------------------+
|  1 | 2018-09-23 16:05:41.000000 |
+----+----------------------------+

秒より小さい精度の値が入ったデータを入れたいと思います.

直接SQLを叩くならば

OK

CREATE TABLE  hoge_OK(rectime DATETIME(6));

とすることで作成できることから,

INSERT INTO hoge_OK(rectime) values(current_timestamp);

試しにデータを入れれば,

MariaDB [hoge]> select * from hoge_OK;
+----------------------------+
| rectime                    |
+----------------------------+
| 2018-09-23 16:05:41.000000 |
+----------------------------+
1 row in set (0.00 sec)

となります.

NG

CREATE TABLE  hoge_NG(rectime DATETIME);

と小数点を指定しないと

INSERT INTO hoge_NG(rectime) values(current_timestamp);

としても,

MariaDB [hoge]> select * from hoge_NG;
+---------------------+
| rectime             |
+---------------------+
| 2018-09-23 16:09:27 |
+---------------------+
1 row in set (0.00 sec)

となります.

peewee では

本題です.

peeweeでデータベースを作成する場合,データベース接続情報,スキーマ定義,テーブル作成コードを作成します.

  • データベース接続情報(db_info.py)
import peewee

# データベース接続(置き換えが必要です)
db = peewee.MySQLDatabase(
    host=HOST,
    database=DATABASE,
    user=USER,
    password=PASSWD
)
import peewee
import db_info

class BaseModel(peewee.Model):
    class Meta:

        # データベース接続情報
        database = db_info.db

class hoge_peewee(BaseModel):
    rectime = peewee.DateTimeField(
        db_column="rectime",
        formats=[
            "%Y-%m-%d %H:%M:%S.%f"
        ]
    )
  • テーブル作成コード(make_table.py)
import logging
import db_info
import db_schema

# ログ出力
logger = logging.getLogger('peewee')
logger.setLevel(logging.DEBUG)
logger.addHandler(logging.StreamHandler())

db_info.db.connect()
db_info.db.create_tables(
    [
        db_schema.hoge_peewee
    ]
)
db_info.db.close()

make_table.pyを実行すると次のようになります.

$ python make_table.py 
('SHOW TABLES', None)
('CREATE TABLE IF NOT EXISTS `hoge_peewee` (`id` INTEGER AUTO_INCREMENT NOT NULL PRIMARY KEY, `rectime` DATETIME NOT NULL)', [])

データを入れようと,

  • データ挿入コード(data_insert.py)
from datetime import datetime
import peewee
import db_info
import db_schema

now = datetime.now().strftime("%Y/%m/%d %H:%M:%S.%f")
print(now)

with db_info.db.transaction():
    db_schema.hoge_peewee.create(
                rectime=now
            )

を実行すると,

$ python data_insert.py 
2018/09/23 16:47:13.780898

問題なく実行できますが,

MariaDB [hoge]> select * from hoge_peewee;
+----+---------------------+
| id | rectime             |
+----+---------------------+
|  1 | 2018-09-23 16:47:13 |
+----+---------------------+
1 row in set (0.00 sec)

秒までしか入っていません.

いろいろと調べてみましたが,

  • Datetimeフィールドをラップして自前でフィールドを用意する
  • テーブル作成のみ別の手段にする

が解決策のようです.

最後に

紹介したSQLコードで作成したテーブルであれば,peewee経由でも秒以下の精度のあるデータを挿入できます.

参考文献

本記事のソースコード

github.com