DjangoでMOBAのランキングを作る②

## はじめに

この記事は以下の記事の続きです。

https://qiita.com/Kazukiya/items/d0691b0a7d8fe18f1706

今回は Django プロジェクトで PostgreSQL と接続し、Heroku 上でテーブルのデータを表示できるようになるまで実装します。

## PostgreSQL と接続する

### 設定

Django プロジェクトで PostgreSQL を使用するには、`settings.py` の `DATABASES` 設定を変更する必要があります。

```python:settings.py
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql",
        "OPTIONS": {
            "service": "moba_ranking",
            "passfile": ".my_pgpass",
        },
    }
}
```

変更したらこの設定に沿うように、PostgreSQL にユーザーとデータベースを作成します。

```sql
psql postgres

CREATE USER moba_ranking_user WITH PASSWORD 'moba_ranking_pass';
CREATE DATABASE moba_ranking_db OWNER moba_ranking_user;
```

作成したユーザーとデータベースの情報をもとに、ホームディレクトリに `.pg_service.conf` と `.my_pgpass` ファイルを作成します。

```:.pg_service.conf
[moba_ranking]
host=localhost
user=moba_ranking_user
dbname=moba_ranking_db
port=5432
```

```:.my_pgpass
localhost:5432:NAME:USER:PASSWORD
```

`settings.py` の `INSTALLED_APPS` に `main` アプリケーションを追加します。

```python:settings.py
INSTALLED_APPS = [
    ...
    'main',
]
```

データベースのマイグレーションを実行します。

```
python manage.py migrate
```

エラーが出なければPostgreSQLの設定は完了です。

### モデルの作成

`main/models.py` に `Hero` モデルを作成します。

```python:models.py
class Hero(models.Model):
    ROLE_CHOICES = [
        ('Support', 'Support'),
        ('Fighter', 'Fighter'),
        ('Tank', 'Tank'),
        ('Assassin', 'Assassin'),
        ('Mage', 'Mage'),
        ('Marksman', 'Marksman'),
    ]

    name_jp = models.CharField(max_length=255)
    name_en = models.CharField(max_length=255)
    role = models.CharField(max_length=20, choices=ROLE_CHOICES)
    image_url = models.URLField()
    article_url = models.URLField()

    def __str__(self):
        return self.name_en
```

モデルの変更を検出し、マイグレーションファイルを作成します。

```
python manage.py makemigrations
python manage.py migrate
```

TablePlus などのデータベースクライアントを使って、テーブルが正しく作成されたことを確認します。

### データの追加

Django のシェルを使ってヒーローのデータを追加します。

```
python manage.py shell
```

下記のコードをシェル上で実行します。

```python
heroes = [
    {
        "name_jp": "ロイン",
        "name_en": "Lolita",
        "role": "Support",
        "image_url": "https://shanbenzzz.com/wp-content/uploads/2023/12/Lolita.webp",
        "article_url": "https://shanbenzzz.com/mobile-legends/hero/tank/lolita"
    },
    {
        "name_jp": "フォヴィウス",
        "name_en": "Phoveus", 
        "role": "Fighter",
        "image_url": "https://shanbenzzz.com/wp-content/uploads/2023/12/Phoveus.webp",
        "article_url": "https://shanbenzzz.com/mobile-legends/hero/fighter/phoveus"
    },
    # ... 他のヒーローのデータ ...
]

from main.models import Hero

for hero_data in heroes:
    hero = Hero(
        name_jp=hero_data["name_jp"],
        name_en=hero_data["name_en"],
        role=hero_data["role"],
        image_url=hero_data["image_url"],
        article_url=hero_data["article_url"]
    )
    hero.save()
```

データが正しく追加されたことを確認します。

### ビューとテンプレートの作成

ヒーローのデータを表示するためのビューとテンプレートを作成します。

`main/templates/main/hero_list.html` を作成し、以下のように記述します。

```html:hero_list.html
<!DOCTYPE html>
<html>
<head>
    <title>Hero List</title>
</head>
<body>
    <h1>Hero List</h1>
    <ul>
        {% for hero in heroes %}
            <li>{{ hero }}</li>
        {% endfor %}
    </ul>
</body>
</html>
```

`main/views.py` に `hero_list` ビューを追加します。

```python:views.py
def hero_list(request):
    heroes = Hero.objects.all().values_list('name_jp', flat=True)
    context = {
        'heroes': heroes
    }
    return render(request, 'main/hero_list.html', context)
```

`main/urls.py` にURLパターンを追加します。

```python:urls.py
urlpatterns = [
    path("", views.hero_list, name="hero_list"),
]
```

開発サーバーを起動し、ルートURLにアクセスしてヒーローのリストが表示されることを確認します。

![127.0.0.1_8000_ (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849608/0e2e215d-de5b-1eb6-88db-ba65d6908573.png)

## Heroku でのデータ表示

Heroku 上でデータを表示するために、以下の手順を実行します。

### データベースアドオンの追加

Heroku アプリにPostgreSQLのアドオンを追加します。
ここは現在Herokuのチュートリアルと違うので注意してください。

```
heroku addons:create heroku-postgresql:essential-2
```

また、アドオンの設定が完了するのにも少し時間がかかるのでそちらもご注意ください。

https://devcenter.heroku.com/articles/getting-started-with-python#provision-and-use-a-database

### 設定の変更

`settings.py` を変更し、Heroku環境では `DATABASE_URL` 環境変数から、ローカル環境では `DATABASES` 設定からデータベース設定を読み込むようにします。

```python:settings.py
if IS_HEROKU_APP:
    DATABASES = {
        "default": dj_database_url.config(
            conn_max_age=600,
            conn_health_checks=True,
            ssl_require=True,
        ),
    }
else:
    DATABASES = {
        "default": {
            "ENGINE": "django.db.backends.postgresql",
            "OPTIONS": {
                "service": "moba_ranking",
                "passfile": ".my_pgpass",
            },
        }
    }
```

### マイグレーションの実行

Heroku 上でマイグレーションを実行します。

```
heroku run python manage.py migrate
```

エラーが無ければOKです。

### カスタム管理コマンドの作成

ヒーローのデータをデータベースに追加するためのカスタム管理コマンドを作成します。

`main/management/commands/load_hero_data.py` を作成し、以下のように記述します。

```python:load_hero_data.py
from django.core.management.base import BaseCommand
from myapp.models import Hero

class Command(BaseCommand):
    help = 'Loads hero data into the database'

    def handle(self, *args, **options):
        hero_data = [...]  # heroデータのリスト

        for hero in hero_data:
            Hero.objects.create(
                name_jp=hero['name_jp'],
                name_en=hero['name_en'],
                role=hero['role'],
                image_url=hero['image_url'],
                article_url=hero['article_url']
            )

        self.stdout.write(self.style.SUCCESS('Hero data loaded successfully'))
```

カスタム管理コマンドを実行し、データを追加します。

```
heroku run python manage.py load_hero_data
```

これで、Heroku 上でも同じようにヒーローのデータが表示されるはずです。

## 管理ページの作成

ヒーローのデータを管理ページでも操作できるようにしておきます。

管理ページを作成するために、以下の手順を実行します。

### 管理ユーザーの作成

管理ユーザーを作成します。

```
python manage.py createsuperuser
```

ユーザー名、メールアドレス、パスワードを入力します。

### 管理ページへのアクセス

`http://127.0.0.1:8000/admin/` にアクセスし、管理ページが表示されることを確認します。

![127.0.0.1_8000_admin_login__next=_admin_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849608/84bf2010-b472-7daf-2689-015615a5e9eb.png)

### モデルの登録

`main/admin.py` に `Hero` モデルを登録します。

```python:admin.py
from django.contrib import admin
from .models import Hero

admin.site.register(Hero)
```

管理ページにログインし、`Hero` モデルが操作できることを確認します。

![127.0.0.1_8000_admin_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849608/1a9dce46-6183-dbbd-9ec9-1873e941a218.png)

## まとめ

この記事では、Django プロジェクトで PostgreSQL と接続し、Heroku 上でデータを表示する方法を説明しました。また、管理ページを作成し、モデルを操作できるようにしました。

次は、スクレイピングしたデータを使ってヒーローの画像のランキングを作成する予定です。

## 続き

https://qiita.com/Kazukiya/items/6b9ab24f6528283db7bf