[Django] ローカルのsqlite3からHerokuのPostgreSQLにデータを移行する


経緯

オープンデータを使ってDjangoでWebアプリケーションを作ろうと思い
csvファイルをsqlite3にインポートしました。
Herokuにデプロイしようとしたら
sqlite3が使えなかったのでローカルに登録したデータを
PostgreSQLに移行するまでのメモです。

csvファイルをインポート

文京区の保育園の一覧をダウンロードしました。
事前にNULLを0に置換するなどデータを加工しておきました。
http://opendata-catalogue.metro.tokyo.jp/dataset/t131059d0206080001

sqlite3 DBファイル名 で起動

$ sqlite3 db.sqlite3

カラムの区切り文字を変更

sqlite> .separator ,

.import csvファイル名 テーブル名でインポート

sqlite> .import hoikuen.csv hoikuen

参考:sqlite3でcsvファイルからインポート

アプリケーションのテーブルにインサート

「hoikuen」テーブルからアプリケーションのデータを登録する「app_item」テーブルに必要なデータだけをインサートしました。
Djangoモデルは以下のとおりです。(バリデーションはまだ実装してないです。)

models.py
from django.db import models

class Item(models.Model):

    CATEGORIES1 = (
        (1, '区立保育園'),
        (2, '私立保育園'),
    )

    CATEGORIES2 = (
        (1, '認可保育園'),
        (2, '認証保育園'),
        (3, '認定こども園'),
        (4, '認可外保育施設'),
    )

    name = models.CharField(
        verbose_name='施設名',
        max_length=200,
    )

    postal_code = models.CharField(
        max_length=8,
        verbose_name='郵便番号'
        )

    address = models.TextField(
        verbose_name='住所',
        max_length=300,
        blank=True
   )

    latitude = models.DecimalField(
        verbose_name='緯度',
        max_digits=9, 
        decimal_places=6, 
        default=0
    )

    longitude = models.DecimalField(
        verbose_name='経度', 
        max_digits=9, 
        decimal_places=6, 
        default=0
    )

    tel_number = models.CharField(
        max_length=15, 
        verbose_name='電話番号'
    )

    category1 = models.IntegerField(
        verbose_name='カテゴリ1',
        choices=CATEGORIES1,
        default=1
    )

    category2 = models.IntegerField(
        verbose_name='カテゴリ2',
        choices=CATEGORIES2,
        default=1
    )

    total = models.IntegerField(
        verbose_name='合計',
        default=0
    )

    year0 = models.IntegerField(
        verbose_name='0歳',
        default=0
    )

    year1 = models.IntegerField(
        verbose_name='1歳',
        default=0
    )
    year2 = models.IntegerField(
        verbose_name='2歳',
        default=0
    )

    year3 = models.IntegerField(
        verbose_name='3歳',
        default=0
    )

    year4_5 = models.IntegerField(
        verbose_name='4・5歳',
        default=0
    )

    created_at = models.DateTimeField(
        verbose_name='登録日',
        auto_now_add=True
    )

    # 以下は管理サイト上の表示設定
    def __str__(self):
        return self.name
import.sql
INSERT INTO app_item 
SELECT "No.",施設名,郵便番号,住所,緯度,経度,電話番号,
 CASE
    WHEN カテゴリ1='区立保育園' THEN '1' 
    WHEN カテゴリ1='私立保育園' THEN '2' 
    ELSE '0'
  END,
 CASE 
    WHEN カテゴリ2='認可保育園' THEN '1'
    WHEN カテゴリ2='認証保育園' THEN '2'
    WHEN カテゴリ2='認定こども園' THEN '3'
    WHEN カテゴリ2='認可外保育施設' THEN '4'   
    ELSE '0'
  END,
 合計園児定員(名),0歳児定員(名),1歳児定員(名),2歳児定員(名),3歳児定員(名),4・5歳児定員(名),
 DATETIME('now', 'localtime')
FROM hoikuen;

csvファイルにエクスポート

herokuデプロイしたものの、登録したデータが空になってしまったのでsqlite3からPostgreSQLにデータを移行します。
(最初からモデルに合わせてcsvを加工しておけばよかったです。)

sqlite>  .mode csv
sqlite>  .output output.csv
sqlite>  SELECT * FROM app_item;

HerokuのDBに接続

Homebrewを使用してPostgreSQLをインストール

$ brew install postresql

参考:MacにHomebrewでPostgreSQLをインストール

Heroku CLIをインストール

$ brew install heroku/brew/heroku

HerokuのPostresSQLへ接続

$ heroku pg:psql

参考:HerokuのDBにローカルPCからアクセスしたいんだけど...

csvファイルをインポート
\COPY テーブル名 FROM 'csvファイル名' WITH CSV

DATABASE=> \COPY app_item FROM 'output.csv' WITH CSV