Python SQLAlchemy Tech

Python SQLAlchemy Modelでテーブル・カラムの文字コードutf8mb4を設定する方法

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

 

  • この記事を書いた人

次世代ペンギン

長いのでペンギンとお呼びください。システム開発・プログラミングのお仕事をしています。甘味とコーヒーは生命線。多くの人に役立つ情報のシェアが目標です。

人気の記事

1

会社員でプログラマーとして働いている人、インフラやネットワークのエンジニアとして働いている人の中には、フリーランスのプログラマーとして独立、もしくは転向したい人もいるので ...

2

キャリアアップのため、または高収入を目指して、しっかりプログラミングを学びたいという人が増えてきましたね。 この記事では現役のエンジニアである私が、実際に仕事で稼げるよう ...

3

フリーランスのプログラマーにとって収入の向上に最も直結するのはスキルです。 必要なスキル、スキルの獲得方法が気になる人も多いでしょう。 また、これからフリーランスを目指す ...

4

Vuetifyの v-progress-circular コンポーネントは、数値データや処理状況を環状(円状)のデザインで教えてくれるUIデザインです。 ローディングのス ...

5

Vuexのstore(ストア)を使うと、各コンポーネント間で個別にデータのやり取りすることなく、データを一元的に管理できます。Vueでは欠かせない機能といえるでしょう。 ...

-Python, SQLAlchemy, Tech
-, , ,