0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

Last updated at Posted at 2024-06-14

はじめに

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

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

環境

Python 3.12.0
Django 5.0.6

結論

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

やろうとしたこと

CartテーブルとCartItemテーブルを作成したい。

事象について

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

今回追加したいテーブルは赤枠の2つ
image.png

管理画面の赤枠のテーブル名を押下すると以下のエラー画面になる。
image.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に適用されない場合に発生するとのことでした。
参考サイト

DBに直接ログインしてテーブルの状態を確認する必要がありそうです。
参考サイト

こちらのサイトでも以下のように記載がありました。

エラー回避のためどうしても直接データベースを変更するケースが出てくる。

参考サイト

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

※コンテナからDBに接続する流れは、以下のサイトを参考にしました。
【Python/Django】よく使うコマンドのまとめ(3)
PostgreSQLの使い方

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

 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というコマンドを使えば、マイグレーションする時に実行するコマンドを確認できると公式ドキュメントに記載があり、試しに打ってみることに。
参考サイト

コマンド: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

ADD CART MODELからレコードが問題なく追加できることを確認。
image.png

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

事象の原因について

詳細な事象の原因については特定に至ってないですが、コンテナが使い捨てを前提として運用する物なのでコンテナ内でマイグレーションを実行した際にマイグレーションが正常に実行されなくなってしまったのではないか。と推測してます。
参考サイト

まとめ

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

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?