SQLAlchemyはPythonからRDBMS(MySQL等)にアクセスするライブラリの一つで、柔軟で多機能なORM機能などが含まれています。
このページでは、文字列・テキストを日本語で格納するために、文字コードをutf8mb4などに変更する方法を、現役のエンジニアが解説しています。
- データベース、テーブル単位でデフォルトの文字コードを設定する方法
- カラム単位で文字コード・参照順位を設定する方法
結論
テーブルのデフォルト文字コードを指定する
class Base(object):
__table_args__ = {
"mysql_default_charset": "utf8mb4",
"mysql_collate": "utf8mb4_general_ci",
}
Base = declarative_base(cls=Base)
Base.query = session.query_property()
テーブルの各カラムごとに文字コード・照合順序を設定する
class TableModel(Base):
#...
column_name = Column(mysql.VARCHAR(40, collation='utf8mb4_general_ci'), nullable=False)
#...
comment = Column(mysql.TEXT(collation='utf8mb4_general_ci'), nullable=False)
#...
Pythonのスキルを使って毎月の収入源を増やすのが最適なんじゃないかという件
実際、今のスキルに合わせて仕事を獲得し、スキマ時間で毎月+5、+20、+70万円くらいの人が多いです。
必要なスキル、仕事の獲得までの流れは以下の記事で徹底解説しています。
(もちろん全部無料です)
空いた時間にぜひ参考にしてみてください。
実行環境
$ mysql --version
mysql Ver 15.1 Distrib 10.3.29-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2
$ python --version
Python 3.9.2
$ pip freeze
PyMySQL==1.0.2
SQLAlchemy==1.4.5
(参考)データベースのデフォルト文字コード設定
開発指針にもよりますが、基本的にはデータベース単位でデフォルトの文字コード・参照順位を設定します。
テーブル、各カラムで文字コードが設定されていなければ、データベースに設定されたデフォルトの文字コードが反映されます。
デフォルト文字コードは、データベースの作成時のcreate
文の
character set [文字コード]
で行います。
MySQL []> CREATE DATABASE db_jpn CHARACTER SET utf8mb4;
Query OK, 1 row affected (0.001 sec)
MySQL [db_jpn]> show variables like 'character\_set\_%';
+--------------------------+---------+
| Variable_name | Value |
+--------------------------+---------+
| character_set_client | binary |
| character_set_connection | binary |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | binary |
| character_set_server | binary |
| character_set_system | utf8 |
+--------------------------+---------+
7 rows in set (0.002 sec)
テーブルのデフォルト文字コード設定
SQLAlchemyのモデル(Model)定義は、ORMを使用したりマイグレーションのときに参照されます。
まずは、文字コード(charset)を全く指定しない場合のマイグレーションを確認してみましょう。
特にカスタマイズせずにBaseクラスを取得します。
Base = declarative_base()
Base.query = session.query_property()
class User(Base):
__tablename__ = 'users'
id = Column(BigInteger, primary_key=True, autoincrement=True, nullable=False)
name = Column(mysql.VARCHAR(100), nullable=False)
affiliation = Column(mysql.VARCHAR(100), nullable=False)
job_title = Column(mysql.VARCHAR(100), nullable=False)
expertise = Column(mysql.VARCHAR(100), nullable=False)
birthday = Column(mysql.DATETIME)
comment = Column(mysql.TEXT(100), nullable=False)
マイグレーションを実行して作成されたテーブルを確認してみると…
MySQL []> show create table users;
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| users | CREATE TABLE `users` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varbinary(100) NOT NULL,
`affiliation` varbinary(100) NOT NULL,
`job_title` varbinary(100) NOT NULL,
`expertise` varbinary(100) NOT NULL,
`birthday` datetime DEFAULT NULL,
`comment` tinyblob NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=binary |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.001 sec)
show create table ...
コマンドで見てみると、DEFAULT CHARSET
がデータベースのデフォルト値(今回はbinary
)となっています。
モデル定義でテーブルのデフォルト文字コードを設定するには以下のようにします。今回、テーブルのデフォルト文字コードとしてutf8mb4
を設定してみます。
モデル定義でデフォルト文字コードを設定するには、Baseクラスにパラメータをセットし、このBaseを継承して各モデルを作成します。
class Base(object):
__table_args__ = {
"mysql_default_charset": "utf8mb4",
"mysql_collate": "utf8mb4_general_ci",
}
Base = declarative_base(cls=Base)
Base.query = session.query_property()
class User(Base):
__tablename__ = 'users'
id = Column(BigInteger, primary_key=True, autoincrement=True, nullable=False)
name = Column(mysql.VARCHAR(100), nullable=False)
affiliation = Column(mysql.VARCHAR(100), nullable=False)
job_title = Column(mysql.VARCHAR(100), nullable=False)
expertise = Column(mysql.VARCHAR(100), nullable=False)
birthday = Column(mysql.DATETIME)
comment = Column(mysql.TEXT(100), nullable=False)
MySQL []> show create table users;
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| users | CREATE TABLE `users` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`affiliation` varchar(100) NOT NULL,
`job_title` varchar(100) NOT NULL,
`expertise` varchar(100) NOT NULL,
`birthday` datetime DEFAULT NULL,
`comment` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
DEFAULT CHARSET=utf8mb4
となっているのを確認できました。
これで各カラムの文字コードも(特段の設定がなければ)utf8mb4
となります。
カラムごとの文字コード設定
データベース単位、テーブル単位で設定されているデフォルトの文字コードではなく、カラムごとに文字コード・参照順位を設定したい場面もあるかと思います。
この場合は、カラムごとに文字コード・照合順序を設定することも可能です。
Base = declarative_base()
Base.query = session.query_property()
class User(Base):
__tablename__ = 'users'
id = Column(BigInteger, primary_key=True, autoincrement=True, nullable=False)
name = Column(mysql.VARCHAR(100, collation='utf8mb4_general_ci'), nullable=False)
affiliation = Column(mysql.VARCHAR(100, collation='utf8mb4_general_ci'), nullable=False)
job_title = Column(mysql.VARCHAR(100, collation='utf8mb4_general_ci'), nullable=False)
expertise = Column(mysql.VARCHAR(100, collation='utf8mb4_general_ci'), nullable=False)
birthday = Column(mysql.DATETIME)
comment = Column(mysql.TEXT(100, collation='utf8mb4_general_ci'), nullable=False)
今回参考にしたページ・資料
Composing Mapped Hierarchies with Mixins — SQLAlchemy 1.4 Documentation