👋

Django ORM で TiDB Serverless に接続する : (1)通常編

に公開

この記事は2回連載です。
もともとTiDB for AIを試そうとしていました。
https://pingcap.github.io/ai/
構成している技術スタックを見たところDjango-ORMが使われており、まずはそちらを纏めようと思いました。

TiDBのドキュメントには DjangORM + Vector Searchのサンプルが以下に提供されています。
https://docs.pingcap.com/tidbcloud/vector-search-integrate-with-django-orm/
ただVector Searchの操作は通常のSQLとは少し異なるため、慣れていないと理解に手間取るところからDjangoの機能とVector Searchの機能をまずは明確に分けて理解していくため、今回は普通のSQL(Create Table, Insert, Select等)をDjango ORMで構築する手順を纏めていきます。

Django と Django ORM

https://www.djangoproject.com/

Django は Python 製の Web アプリケーションフレームワークです。Web サービスの開発に必要な機能が フルスタックで揃っており、その中の一つの機能として ORM(Object-Relational Mapping) が標準搭載されています。これにより、データベースとの接続や操作が簡潔に行えるようになっています。

これまでに PrismaDrizzleSequelizeTypeORM の4つの ORM を見てきましたが、これらはすべて「データベース操作に特化したライブラリ」です。一方で Django は フルスタックな Web フレームワークであり、その中の一機能として ORM(Django ORM)が提供されているという点が大きな違いです。

このような関係のためDjangoをデータベースと連携させると以下の様にシステムテーブルが複数生成されます。

さっそくやってみます

すべての学習は最もシンプルな手組から始めるのが一番理解が深まりやすと思っていますのでまずは単純な構成から。

1.必要ライブラリのインストール

まずは環境を構築していきます。作業ディレクトリを作ります。

mkdir tidb-django-demo
cd tidb-django-demo

仮想環境を作成しActivateします。

python3 -m venv .venv
source .venv/bin/activate

必要なライブラリやdjango本体をインストールします。

pip install django mysqlclient
sudo apt-get install default-libmysqlclient-dev build-essential -y

2.プロジェクトの初期化とアプリケーション作成

開発を始める際にまず「プロジェクト」を作成し、その中に「アプリケーション(app)」を作成して機能を分割していくのが一般的なようです。一つのプロジェクトの中に複数のアプリケーションを作成することが可能ですので、TiDB Serverlessへの接続をアプリケーションとして設定していきます。

プロジェクト:
Webサービス全体の構成や設定を管理する単位です。

  • 設定ファイル(settings.py)やURLルーティング(urls.py)などが含まれます。
  • サイト全体の設定や構成管理を担います。

アプリケーション:
Webサービス内の個別の機能単位(モジュール)です。

  • 例:ブログ機能、認証機能、商品管理機能、データベース接続機能、など
  • 各アプリケーションは再利用可能な形で分離することができます。

まずはプロジェクトを作成します。

django-admin startproject myproject .
.
├── manage.py
└── myproject
    ├── __init__.py
    ├── asgi.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

つぎにsampleという名前のアプリケーションを作成します。

python manage.py startapp sample
.
├── manage.py
├── myproject
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-312.pyc
│   │   └── settings.cpython-312.pyc
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── sample
    ├── __init__.py
    ├── admin.py
    ├── apps.py
    ├── migrations
    │   └── __init__.py
    ├── models.py
    ├── tests.py
    └── views.py

3. TiDB Serverless への接続設定

まずDjangoからTiDB Serverlessへの接続は電子証明書を使います。証明書はTiDB Cloudのマネージメントコンソールからダウンロードできますが基本ユーザー共通です。以下のファイルをcert.pemという名前に作成します。

cert.pem
-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
-----END CERTIFICATE-----

次にmyproject/settings.pyを修正します。
DATABASESブロックを以下に置換します。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'test',
        'USER': '<userid>',
        'PASSWORD': '<password>',
        'HOST': 'gateway01.us-west-2.prod.aws.tidbcloud.com',
        'PORT': '4000',
        'OPTIONS': {
            'ssl': {
                'ca': 'cert.pem'
            }
        }
    }
}

<userid>,<passowrd>やその他は皆さんの環境ごとに置き換えます。ENGINEdjango.db.backends.mysqlとなっています。これはDjango用MySQLドライバです。
INSTALLED_APPSブロックの一番最後にsampleを追加します。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'sample',
]

4. データベースのモデル定義

次にアプリケーションがデータベースへの接続の際に使用するモデルを定義します。
/sample/models.pyを以下に置換します。

# sample/models.py

from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.CharField(max_length=100)

これによりsample_bookという名前でTiDB Serverlessにテーブルが作成されます。

5. マイグレーション

Djangoでは設定を反映させることをマイグレーションといいます。いままの手順で作成した設定内容をもとにTiDB Serverlessへの接続を行いテーブルを作成します。

python manage.py makemigrations sample

このコマンドは、Django アプリケーションの モデル(models.py)に加えた変更をマイグレーションファイルとして記録するためのものです。
次に反映された変更をTiDB Serverlessへ反映させます。

python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sample, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying sample.0001_initial... OK
  Applying sessions.0001_initial... OK

このタイミングで以下の通りDjango用システムテーブルと先ほど定義したbookテーブルが作成されています。

6. テスト

ではテストを行います。
python manage.py shell
こちらでシェルを起動します。以下をシェルに貼り付けます。

from sample.models import Book

# INSERT
Book.objects.create(title="TiDBとDjango", author="山田太郎")

# SELECT
for book in Book.objects.all():
    print(book.title, book.author)

このように出力されます。

>>> from sample.models import Book
ook in Book.objects.all():
    print(book.title, book.author)>>>
>>> # INSERT
>>> Book.objects.create(title="TiDBとDjango", author="山田太郎")

<Book: Book object (1)>
>>>
>>> # SELECT
>>> for book in Book.objects.all():
...     print(book.title, book.author)
...
TiDBとDjango 山田太郎
>>>

TiDB CloudのSQL Editorでuse test;select * from sample_book;を実行するとデータが書き込まれていることがわかります。

シェルはexit()で抜けることができます。
次にtest.pyファイルを作成します。

test.py
# test_orm.py
import os
import django

# Django 設定を使えるようにする
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myproject.settings")
django.setup()

# モデルのインポート
from sample.models import Book

# データの挿入
Book.objects.create(title="スクリプトからの挿入", author="テスト太郎")

# データの取得
for book in Book.objects.all():
    print(f"{book.id}: {book.title} - {book.author}")

python test.pyで実行すればデータの書き込みと読み込み結果が出力されます。

Next Step

次回は、このDjango ORMを活用しながら、TiDB Serverlessが提供する Vector Search 機能を実際に試していきます。

また公式にはVector Searchとの連携のほかに、簡単なゲームを楽しめるサンプルが提供されています。
https://docs.pingcap.com/ja/tidb/stable/dev-guide-sample-application-python-django/
こちらはあらかじめ様々な機能が実装されているため、ぜひNextStepとして合わせてご参考にしてみてください。

Discussion