[Django]既存のデータベースを利用する方法


## この記事について

Djangoから既存のデータベースを利用する方法のメモです。
**既存システムの管理ツールをDjangoで開発する**という状況を想定しています。

参考：[公式 レガシーなデータベースと Django の統合](https://docs.djangoproject.com/ja/2.1/howto/legacy-databases/)

## Djangoで利用できるデータベース

Djangoで利用可能なデータベースサーバは公式でPostgresSQL、MySQL、Oracle、[非公式でSQLServer](django-pyodbc-azure)をサポートしています。メジャーどころは抑えていますが、バージョンに制限があるので注意しましょう。

- [Django公式：利用可能なデータベース](https://docs.djangoproject.com/ja/2.1/ref/databases/)

※バージョン Django 2.1 時点

| データベース | バージョン |
|:--|:--|
| PostgreSQL |9.4 以上|
| Oracle | 12.1 以上|
| MySQL | 5.6 以上|
|SQLServer|2008 以上|

## 注意すべき点

Djangoの起動にはいくつかの管理用テーブル（名前がauthとかdjangoで始まるテーブル）が必要になるため、既存のデータベースに全く手を加えず使うことはできません。Djangoが使用する接続ユーザーにはテーブルの作成権限を付けて、マイグレーションを実行できるようにする必要があります。

マイグレーション時に作られるDjango用のテーブルは10数個です。
管理面で気になるなら、事前にDjango用のスキーマを作ってそこに作成されるようにしましょう。既存システムのテーブルも、あらかじめそこにエイリアスを作り最低限の権限を与えておけば安全です。

なお、Djangoでは主キーが無いテーブル、主キーが複合キーであるテーブルは利用できません。

## 作業内容

### １．データベースに接続する

まず各データベースへの接続に必要なライブラリをpipでインストールします。

| データベース | バージョン |
|:--|:--|
|PostgreSQL|psycopg2|
|MySQL|mysqlclient|
|Oracle|cx_Oracle|
|SQLServer|django-pyodbc-azure|

SQLServerを利用する場合はOSにODBCドライバもインストールします。

※ ODBCドライバはLinux向けもあります。
参考： [LinuxからSQL ServerにODBCで接続する](https://qiita.com/arachan@github/items/5863c945dbe7507975d8)

その後settings.pyのDATABASESを修正します。

- [Django 公式：データベース接続設定の書き方]( https://docs.djangoproject.com/en/2.1/ref/settings/#databases)

例：postgres

```python:settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'mydatabase',
        'USER': 'mydatabaseuser',
        'PASSWORD': 'mypassword',
        'HOST': '127.0.0.1',
        'PORT': '5432', 
    }
}
```

例：SQLServer ODBCの設定が必要

```python:settings.py

DATABASES = {
    'default': {
        'ENGINE': 'sql_server.pyodbc',
        'NAME': 'mydb',
        'USER': 'user@myserver',
        'PASSWORD': 'password',
        'HOST': 'myserver.database.windows.net',
        'PORT': '',

        'OPTIONS': {
            'driver': 'ODBC Driver 13 for SQL Server',
        },
    },
}
```

設定がうまくいったかどうかは管理コマンド`manage.py dbshell`でわかります。

### ２．inspectdbでモデル定義のコードを調べる

Djangoには既存テーブルを読み取ってモデル定義を作るための管理コマンドがあります。

```
usage: manage.py inspectdb [-h] [--database DATABASE] [--include-views]
                           [--version] [-v {0,1,2,3}] [--settings SETTINGS]
                           [--pythonpath PYTHONPATH] [--traceback]
                           [--no-color]
                           [table [table ...]]
```

ここで出力されたコードをmodels.pyに定義します。

```python:models.py
class SampleItem(models.Model):
    id = models.IntegerField(primary_key=True)  # AutoField?
    name = models.CharField(max_length=15)

    class Meta:
        managed = False
        db_table = 'sample'
```

データの追加を行うテーブルである場合、idの定義をIntegerFieldからAutoFieldに変更する必要があります。

class Meta: 以降では以下の設定をしています。

- `managed = False`: migrationsの管理対象外とする
- `db_table = 'sample'`: テーブル名を明示

参考：[のぶLab. Djangoで既存のデータベースを使う](http://atsuya046.hatenablog.com/entry/2013/12/29/200514)

### ３．マイグレーション

モデルの定義が済んだらマイグレーションを実行します。対象のデータベースにDjangoの管理テーブルが作成されます。

既存テーブルのデータにアクセスは、`manage.py shell`より`既存テーブルのモデル名.objects.first()`などを実行して確認しましょう。

あとは問題なく`manage.py runserver`でアプリケーションが起動ができるはずです。