created: 2026/01/02,
modified: 2026/01/04
DB Django
AWSコンソールでRDSサービスに移動し、MySQLデータベースを作成します。
料金最安を目指す
同ページ下部の「接続」セクションでEC2を指定
接続: EC2コンピューティングリソースに接続
sudo dnf install mariadb105 mariadb105-devel
インストール後、接続テストを実行:
mysql --version
# RDSエンドポイントへの接続テスト
mysql -h your-rds-endpoint.region.rds.amazonaws.com -u your_master_username -p
MariaDBについて
Amazon Linux 2023では、MySQL互換のMariaDBクライアントがデフォルトで提供されています。
つまり、`mariadb105`をインストールしても、RDS MySQLへの接続や操作には全く問題ありません。実際、多くのLinuxディストリビューションで、MySQLクライアントの代替としてMariaDBクライアントが採用されています。
# 仮想環境をON
cd /var/www/django-5
source venv/bin/activate
pip install mysqlclient
# または
pip install pymysql
# 仮想環境をOFF
deactivate
RDSインスタンスを作成した後、実際に使用するデータベースを作成する必要があります。以下の手順で進めます。
# マスターユーザーで接続
mysql -h your-rds-endpoint.region.rds.amazonaws.com -u your_master_username -p
# パスワードを入力
# データベース名
myfirst_database_2512
-- 接続後、MySQLプロンプトで以下を実行
CREATE DATABASE myfirst_database_2512 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- データベースが作成されたか確認
SHOW DATABASES;
-- データベースを選択
USE myfirst_database_2512;
-- 接続を終了
EXIT;
セキュリティ向上のため、機密情報を環境変数で管理します。
`.env`ファイルは、Djangoプロジェクトのルートディレクトリ(manage.pyがあるディレクトリ)に配置します。
# ディレクトリ構造の例
/var/www/django-5/
├── manage.py
├── .env # ← ここに配置
├── myproject/
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── myapp/
└── venv/
`.env`ファイルを読み込むために、`python-dotenv`をインストールします。
# 仮想環境がONの状態で実行
cd /var/www/django-5
source venv/bin/activate
pip install python-dotenv
# 1. プロジェクトルートに移動
cd /var/www/django-5
# 2. .envファイルを作成
vi .env
# 3. 以下の内容を記述
DB_NAME=your_database_name # 前項2で作成したデータベース名
DB_USER=your_master_username # RDS作成時のマスターユーザー名
DB_PASSWORD=your_password # RDS作成時のマスターパスワード
DB_HOST=your-rds-endpoint.region.rds.amazonaws.com
DB_PORT=3306
# 4. 保存して閉じる(viの場合: ESCキー → :wq → Enter)
.envファイルのセキュリティ上の注意
# .gitignore に以下を追加
.env
*.env
chmod 600 .env
# settings.py の先頭に追加
import os
from pathlib import Path
from dotenv import load_dotenv
# .envファイルを読み込む
load_dotenv()
# 既存のBASE_DIR設定の下に以下を追加
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': os.environ.get('DB_NAME'),
'USER': os.environ.get('DB_USER'),
'PASSWORD': os.environ.get('DB_PASSWORD'),
'HOST': os.environ.get('DB_HOST'),
'PORT': os.environ.get('DB_PORT', '3306'),
'OPTIONS': { # MySQL Strict Mode ON
'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
}
}
}
**MySQL Strict Mode を有効にします**
# 仮想環境ONの状態で
python manage.py check
# モデルを変更したとき
python manage.py makemigrations
# データベース接続テスト
python manage.py migrate
**1. python manage.py check の成功例**
(venv) [ec2-user@ip-172-31-35-28 django-5]$ python manage.py check
System check identified no issues (0 silenced).
この出力が表示されれば、Django設定に問題がないことを示します。
**2. python manage.py migrate の成功例**
(venv) [ec2-user@ip-172-31-35-28 django-5]$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, 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 sessions.0001_initial... OK
各マイグレーションが「OK」と表示されれば、データベース接続とテーブル作成が正常に完了しています。
接続エラーの場合
django.db.utils.OperationalError: (2003, "Can't connect to MySQL server on 'your-rds-endpoint' (110)")
# または
django.db.utils.OperationalError: (1045, "Access denied for user 'username'@'ip-address' (using password: YES)")
よくある失敗の原因:
DjangoのモデルではなくMySQL CLIで直接テーブルを作成する場合の手順です。
# EC2インスタンスからRDSに接続
mysql -h your-rds-endpoint.region.rds.amazonaws.com -u your_master_username -p
# パスワードを入力
# 使用するデータベースを選択
USE your_database_name;
# 現在のデータベースを確認
SELECT DATABASE();
商品テーブルの例:
CREATE TABLE products (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(200) NOT NULL COMMENT '商品名',
price INT NOT NULL COMMENT '価格',
description TEXT COMMENT '説明',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '作成日時',
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新日時'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO products (name, price, description) VALUES
('ノートパソコン', 98000, '高性能な15インチノートパソコン'),
('マウス', 2500, 'ワイヤレスマウス'),
('キーボード', 5800, 'メカニカルキーボード'),
('モニター', 35000, '27インチ4Kモニター'),
('USBメモリ', 1200, '32GB USBメモリ');
-- 全データを表示
SELECT * FROM products;
-- 件数を確認
SELECT COUNT(*) FROM products;
-- 特定の条件で検索
SELECT * FROM products WHERE price > 3000;
-- テーブル構造を表示
DESCRIBE products;
-- または
SHOW CREATE TABLE products;
-- MySQLから切断
EXIT;
-- または
quit;
MySQL CLIで直接作成したテーブルをDjangoで使用する場合:
# 既存のテーブルからモデルを自動生成
# 【注意】上書きされる
python manage.py inspectdb products > myapp/models.py
# 既存のmodels.pyを上書きせず、別ファイルに出力
python manage.py inspectdb products > myapp/models_generated.py
まず、アプリ内の`models.py`でモデル(テーブル定義)を作成します。
# myapp/models.py
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=200, verbose_name='商品名')
price = models.IntegerField(verbose_name='価格')
description = models.TextField(verbose_name='説明', blank=True)
created_at = models.DateTimeField(auto_now_add=True, verbose_name='作成日時')
updated_at = models.DateTimeField(blank=True, null=True, db_comment='更新日時')
class Meta:
verbose_name = '商品'
verbose_name_plural = '商品'
def __str__(self):
return self.name
モデルを作成したら、データベースにテーブルを作成します。
# 仮想環境ONの状態で
python manage.py makemigrations
python manage.py migrate
はい、その理解で正しいです。`models.py`にモデルを定義して、これらのコマンドを実行することでテーブルが作成されます。
# makemigrationsの実行
$ python manage.py makemigrations
Migrations for 'myapp':
myapp/migrations/0001_initial.py
- Create model Product
# migrateの実行
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, myapp, sessions
Running migrations:
Applying myapp.0001_initial... OK
テーブルが作成されたか確認するには、MySQL CLIで:
-- RDSに接続
mysql -h your-rds-endpoint -u your_username -p
-- データベースを選択
USE your_database_name;
-- テーブル一覧を表示
SHOW TABLES;
-- テーブル構造を確認
DESCRIBE myapp_product;
これで`myapp_product`テーブル(アプリ名_モデル名の形式)が作成されていることが確認できます。
MySQL CLIで既にテーブルを作成している場合、Djangoのマイグレーションで同じ名前のテーブルは作成されません。しかし、カラムの不一致がある場合は注意が必要です。
方法1: Djangoモデルを既存テーブルに合わせる
# myapp/models.py
from django.db import models
class Product(models.Model):
id = models.AutoField(primary_key=True) # 明示的に定義
name = models.CharField(max_length=200, verbose_name='商品名')
price = models.IntegerField(verbose_name='価格')
description = models.TextField(verbose_name='説明', blank=True)
created_at = models.DateTimeField(auto_now_add=True, verbose_name='作成日時')
updated_at = models.DateTimeField(auto_now=True, verbose_name='更新日時') # 追加
class Meta:
db_table = 'products' # 既存のテーブル名を指定
managed = False # Djangoにテーブルを管理させない場合
def __str__(self):
return self.name
方法2: inspectdbで既存テーブルからモデルを生成
# 既存テーブルからDjangoモデルを自動生成
python manage.py inspectdb products > myapp/models_from_db.py
# 生成されたモデルを確認して、models.pyにコピー
方法3: マイグレーションをフェイクする
# 既存テーブルに対してマイグレーションを「適用済み」として記録
python manage.py migrate --fake-initial
開発初期段階では、Djangoのマイグレーション機能だけを使うことをおすすめします。MySQL CLIで直接テーブルを作成すると、Djangoとの整合性が取りづらくなります。
既にCLIでテーブルを作成してしまった場合は、`inspectdb`コマンドでモデルを生成し、それを基に調整するのが最も確実です。
from django.db import models
class Products(models.Model):
name = models.CharField(max_length=200, db_comment='商品名')
price = models.IntegerField(db_comment='価格')
description = models.TextField(blank=True, null=True, db_comment='説明')
created_at = models.DateTimeField(blank=True, null=True, db_comment='作成日時')
updated_at = models.DateTimeField(blank=True, null=True, db_comment='更新日時')
class Meta:
managed = False
db_table = 'products'
`inspectdb`コマンドの結果に`id`フィールドが表示されていないのは正常な動作です。これはDjangoの仕様によるものです。
MySQL CLIでテーブル構造を確認してみましょう:
DESCRIBE products;
おそらく以下のような構造になっているはずです:
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(200) | NO | | NULL | |
| price | int | NO | | NULL | |
| description | text | YES | | NULL | |
| created_at | datetime | YES | | NULL | |
| updated_at | datetime | YES | | NULL | |
+-------------+--------------+------+-----+---------+----------------+
このまま使用できます:
# myapp/models.py
from django.db import models
class Products(models.Model):
name = models.CharField(max_length=200, db_comment='商品名')
price = models.IntegerField(db_comment='価格')
description = models.TextField(blank=True, null=True, db_comment='説明')
created_at = models.DateTimeField(blank=True, null=True, db_comment='作成日時')
updated_at = models.DateTimeField(blank=True, null=True, db_comment='更新日時')
class Meta:
managed = False
db_table = 'products'
def __str__(self):
return self.name
idフィールドは自動的に利用可能:
# ビューなどで使用する場合
product = Products.objects.get(id=1) # idは自動的に存在する
print(product.id) # 問題なく動作
もし明示的に`id`フィールドを定義したい場合は、以下のように追加できます:
class Products(models.Model):
id = models.AutoField(primary_key=True) # 明示的に定義
name = models.CharField(max_length=200, db_comment='商品名')
price = models.IntegerField(db_comment='価格')
description = models.TextField(blank=True, null=True, db_comment='説明')
created_at = models.DateTimeField(blank=True, null=True, db_comment='作成日時')
updated_at = models.DateTimeField(blank=True, null=True, db_comment='更新日時')
class Meta:
managed = False
db_table = 'products'
Django Adminは管理画面用のツールです。モデルをAdminに登録すると、ブラウザからデータの追加・編集・削除ができます。
admin.pyでモデルを登録:
# myapp/admin.py
from django.contrib import admin
from .models import Product
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
list_display = ('name', 'price', 'created_at') # 一覧に表示する項目
search_fields = ('name',) # 検索可能な項目
list_filter = ('created_at',) # フィルタ項目
Admin画面にアクセスするためのスーパーユーザーを作成します。
python manage.py createsuperuser
# ユーザー名、メールアドレス、パスワードを入力
スーパーユーザー情報の保存場所
`python manage.py createsuperuser`で作成したユーザー情報は、Djangoのデフォルトの認証システムによって管理され、データベースに保存されます。
保存先テーブル (MySQL)
Django shellで確認:
python manage.py shell
# Pythonシェル内で
from django.contrib.auth.models import User
# 全ユーザーを表示
users = User.objects.all()
for user in users:
print(f"ID: {user.id}, Username: {user.username}, Superuser: {user.is_superuser}")
# スーパーユーザーのみ表示
superusers = User.objects.filter(is_superuser=True)
for user in superusers:
print(f"{user.username} - {user.email}")
関連する他のテーブル
Djangoの認証システムは、複数のテーブルで構成されています:
セキュリティに関する注意
パスワードの変更方法
# 管理コマンドでパスワードを変更
python manage.py changepassword username
# または Django shell で
python manage.py shell
from django.contrib.auth.models import User
user = User.objects.get(username='username')
user.set_password('new_password')
user.save()
まとめ
views.pyでビューを作成:
# myapp/views.py
from django.shortcuts import render
from .models import Product
def product_list(view):
products = Product.objects.all() # 全商品を取得
return render(request, 'myapp/product_list.html', {'products': products})
urls.pyでURLを設定:
# myproject/urls.py
from django.contrib import admin
from django.urls import path
from myapp import views
urlpatterns = [
path('admin/', admin.site.urls),
path('products/', views.product_list, name='product_list'),
]
テンプレートを作成:
<!-- myapp/templates/myapp/product_list.html -->
<!DOCTYPE html>
<html>
<head>
<title>商品一覧</title>
</head>
<body>
<h1>商品一覧</h1>
<table border="1">
<tr>
<th>商品名</th>
<th>価格</th>
<th>説明</th>
</tr>
{% for product in products %}
<tr>
<td>{{ product.name }}</td>
<td>{{ product.price }}円</td>
<td>{{ product.description }}</td>
</tr>
{% endfor %}
</table>
</body>
</html>
MySQLでは5件のデータが確認できるのに、Djangoのビューで「商品が0個」と表示される場合があります。
この問題は、Djangoのモデルが参照しているテーブルと、実際のデータが入っているテーブルが異なることが原因です。
上記の例では:
方法1: モデルの`db_table`を正しく設定する
`models.py`で、正しいテーブル名を指定します:
class Product(models.Model):
name = models.CharField(max_length=200, db_comment='商品名')
price = models.IntegerField(db_comment='価格')
description = models.TextField(blank=True, null=True, db_comment='説明')
created_at = models.DateTimeField(blank=True, null=True, db_comment='作成日時')
updated_at = models.DateTimeField(blank=True, null=True, db_comment='更新日時')
class Meta:
managed = False
db_table = 'products' # ここで正しいテーブル名を指定
方法2: Django shellで確認する
どのテーブルを参照しているか確認します:
python manage.py shell
from myapp.models import Product
# モデルが参照しているテーブル名を確認
print(Product._meta.db_table) # 'myapp_product' または 'products' が表示される
# データを取得してみる
products = Product.objects.all()
print(products.count()) # 件数を確認
print(products) # データの内容を確認
方法3: 生のSQLで確認する
Django shellから直接SQLを実行して確認:
from django.db import connection
with connection.cursor() as cursor:
# myapp_product テーブルの内容を確認
cursor.execute("SELECT * FROM myapp_product")
rows = cursor.fetchall()
print(f"myapp_product: {len(rows)}件")
# products テーブルの内容を確認
cursor.execute("SELECT * FROM products")
rows = cursor.fetchall()
print(f"products: {len(rows)}件")