djangoでDBマイグレーションがうまくいかず、ERROR:  relation "テーブル名" does not existで詰まった件

#### はじめに

みなさん、こんにちは。ゆうたです。

今回はタイトルにも記載した、djangoでDBテーブルが作成できない事象に遭遇したので記事にしたいと思います。
※初学者なので認識相違があればご指摘頂けますと幸いです。

#### 環境
```
Python 3.12.0
Django 5.0.6
```

#### 結論
DBに直接ログインしてテーブルを作成

### やろうとしたこと
CartテーブルとCartItemテーブルを作成したい。

#### 事象について
DBマイグレーションを実行して管理画面にテーブルは表示されるものの、管理画面からレコードをINSERTしようとすると`ERROR:  relation "テーブル名" does not exist`というメッセージでエラーが出力される。

今回追加したいテーブルは赤枠の２つ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624620/67293593-0852-b7bd-3bc4-923eb336cfcd.png)

管理画面の赤枠のテーブル名を押下すると以下のエラー画面になる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624620/70a50e28-5fb8-c300-7490-f7c61dd64c12.png)


#### 各種ファイル
```models.py
from django.db import models

# Create your models here.

class BaseMeta(models.Model):
  created_at = models.DateTimeField(auto_now_add=True)
  updated_at = models.DateTimeField(auto_now=True)

  class Meta:
     abstract = True


class CartModel(BaseMeta):
    cart_id = models.BigAutoField(primary_key=True)


class CartItemModel(BaseMeta):
    name = models.ForeignKey(ProductModel, on_delete=models.CASCADE)
    quantity = models.IntegerField(default=1)
    cart_id = models.ForeignKey(CartModel, on_delete=models.CASCADE)
```

```docker-compose.yml
version: "3.9"

services:
  db:
    image: postgres
    platform: linux/amd64
    volumes:
      - db-data:/var/lib/postgresql/data
    ports:
      - "5433:5432"
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_DB=django_develop #データベース名
      - POSTGRES_PASSWORD=XXXX
    healthcheck:
      test: "psql -U postgres"
      interval: 5s
      timeout: 5s
      retries: 5

  web:
    build: .
    command: python manage.py runserver 0.0.0.0:3000
    volumes:
      - .:/code
    ports:
      - "3000:3000"
    depends_on:
      db:
        condition: service_healthy

volumes:
  db-data:
  ```


#### 調べてわかったこと
以下のサイトから今回のエラーはマイグレーションがDBに適用されない場合に発生するとのことでした。
[参考サイト](https://forum.djangoproject.com/t/deploying-with-postgres-programmingerror-line-1-select-count-as-count-from-landings-pagecontent/19446/2)

DBに直接ログインしてテーブルの状態を確認する必要がありそうです。
[参考サイト](https://forum.djangoproject.com/t/deploying-with-postgres-programmingerror-line-1-select-count-as-count-from-landings-pagecontent/19446/4)

こちらのサイトでも以下のように記載がありました。
>エラー回避のためどうしても直接データベースを変更するケースが出てくる。

[参考サイト](https://qiita.com/okoppe8/items/c9f8372d5ac9a9679396#managepy-migrate---fake-%E3%81%AE%E4%BD%BF%E3%81%84%E3%81%A9%E3%81%93%E3%82%8D)

ということでコンテナからDBにログインしてテーブルの状態を見ていきます。

※コンテナからDBに接続する流れは、以下のサイトを参考にしました。
[【Python/Django】よく使うコマンドのまとめ(3) <PostgreSQLの操作>](https://qiita.com/_whitecat_22/items/264b13f9d7c2f020a7ad)
[PostgreSQLの使い方](https://www.javadrive.jp/postgresql/#section_connect)

DBコンテナを起動しコンテナにログイン
コマンド：`docker-compose exec <コンテナ名> bash`

コンテナにログイン後、postgresqlに接続
コマンド：`psql -U postgres`

データベースの一覧を確認する
※\はMacのキーボードから option + ¥ で入力可

コマンド：`\l`
```
                                                         List of databases
　　　　　　　　　　　　Name      |  Owner   | Encoding | Locale Provider |  Collate   |   Ctype    | ICU Locale | ICU Rules |   Access privileges   
----------------+----------+----------+-----------------+------------+------------+------------+-----------+-----------------------
 django_develop | postgres | UTF8     | libc            | en_US.utf8 | en_US.utf8 |            |           | 
 postgres       | postgres | UTF8     | libc            | en_US.utf8 | en_US.utf8 |            |           | 
```


指定したデータベースへ接続する
コマンド：`\c django_develop`

テーブル一覧を表示
コマンド：`\d`
```                        List of relations
 Schema |               Name                |   Type   |  Owner   
--------+-----------------------------------+----------+----------
 public | Ec_OrderdModel                    | table    | postgres
 public | Ec_OrderdModel_id_seq             | sequence | postgres
 public | Ec_ProductModel                   | table    | postgres
 public | Ec_ProductModel_id_seq            | sequence | postgres
 ```

ここまでの調査でマイグレーションしたにも関わらず、CartテーブルとCartItemテーブルが存在しないことが判明しました。


#### 解消したやり方
DBコンテナにログインし、PostgreSQLに接続してCREATE TABLEで直接テーブルを作成

色々調べながらコンテナの中で直接テーブルを作成しようとするも中々うまくいかない。。
※特にデータ型の指定をどういう風に指定すればいいかわからない。
```
失敗例

django_develop=# CREATE TABLE "CartModel" (
django_develop(# "cart_id" BigAutoField NOT NULL PRIMARY KEY
django_develop(# );
ERROR:  type "bigautofield" does not exist
LINE 2: "cart_id" BigAutoField NOT NULL PRIMARY KEY
                  ^
django_develop=# 
```

調べていくうちに`sqlmigrate`というコマンドを使えば、マイグレーションする時に実行するコマンドを確認できると公式ドキュメントに記載があり、試しに打ってみることに。
[参考サイト](https://docs.djangoproject.com/ja/5.0/intro/tutorial02/#activating-models)

コマンド：`python3 manage.py sqlmigrate <アプリ名> <マイグレーションファイル名>`
```
BEGIN;

Create model CartModel

CREATE TABLE "ec_cartmodel" ("created_at" timestamp with time zone NOT NULL, "updated_at" timestamp with time zone NOT NULL, "cart_id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY);

Create model CartItemModel

CREATE TABLE "ec_cartitemmodel" ("id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, "created_at" timestamp with time zone NOT NULL, "updated_at" timestamp with time zone NOT NULL, "quantity" integer NOT NULL, "cart_id_id" bigint NOT NULL, "name_id" bigint NOT NULL);

COMMIT;
```

データ型が定義されてるので上記の`CREATE TABLE`コマンドをコピーしてDBコンテナから手動でテーブルを作成すると、、
```
django_develop=# CREATE TABLE "ec_cartmodel" ("created_at" timestamp with time zone NOT NULL, "updated_at" timestamp with time zone NOT NULL, "cart_id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY);
CREATE TABLE
```
コマンドが問題なく通った！
`\d`コマンドでテーブル一覧を確認すると`ec_cartmodel`テーブルが作成されている！
```
django_develop=# \d
                        List of relations
 Schema |               Name                |   Type   |  Owner   
--------+-----------------------------------+----------+----------
 public | Ec_OrderdModel                    | table    | postgres
 public | Ec_OrderdModel_id_seq             | sequence | postgres
 public | Ec_ProductModel                   | table    | postgres
 public | Ec_ProductModel_id_seq            | sequence | postgres
 public | ec_cartmodel                      | table    | postgres
 public | ec_cartmodel_cart_id_seq          | sequence | postgres
```

管理画面にログインしCart modelsテーブルにログイン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624620/e98a4ccf-989a-6f63-3347-99fbb415253a.png)


ADD CART MODELからレコードが問題なく追加できることを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624620/1ea17699-b9ee-0ff7-640e-70a3cdda850c.png)

Cartテーブルと同様の流れでCartItemテーブルも正常に作成することができました。

#### 事象の原因について
詳細な事象の原因については特定に至ってないですが、コンテナが使い捨てを前提として運用する物なのでコンテナ内でマイグレーションを実行した際にマイグレーションが正常に実行されなくなってしまったのではないか。と推測してます。
[参考サイト](https://forum.djangoproject.com/t/users-customuser-does-not-exist/9951/3)

#### まとめ
コンテナを使った開発だとトラブルシュートの難易度が少し上がる気がしますが、コンテナ技術は開発をする上で大変便利なものという理解はしてるので、引き続き学習を続けていきたいと思います。