Djangoで掲示板を作成する

:::note warn
この記事は2025/01/03に書かれました。
:::
## Djangoで掲示板を作成する

この記事では、ローカル環境にMAMPを使用し、PythonとDjangoを使った簡単な掲示板(BBS)を作成する手順を説明します。

### 前提条件
- **MAMP**: ローカルサーバー環境を構築します(Mac/Windows)

https://www.mamp.info/en/mac/

https://www.mamp.info/en/mamp/windows/
- **Python**: プログラミング言語(バージョン3.10以上を推奨します)

https://www.python.org/downloads/
- **Django**: Pythonのフレームワーク
- **VS Code**: 一般的な開発用エディタ

https://code.visualstudio.com/download

---

# 目次
- [step-1 プロジェクトを構成する](#1-プロジェクトを構成)
- [step-2 モデルを作成する](#2-モデルの作成)
- [step-3 管理画面の設定する](#3-管理画面の設定)
- [step-4 ビューとurlの設定する](#4-ビューとurlの設定)
- [step-5 テンプレートの作成する](#5-テンプレートの作成)
- [step-6 新規登録機能の追加する](#6-新規登録機能の追加)
- [step-7 編集機能の追加する](#7-編集機能の追加)
- [step-8 削除機能の追加する](#8-削除機能の追加)
- [step-9 動作確認する](#9-動作確認)

---

### 1. プロジェクトを構成

#### 1-1. プロジェクトのセットアップ

ターミナルを開き、プロジェクト用のディレクトリを作成し移動します。

```bash
mkdir django_app
cd django_app
```

仮想環境を作成して有効化します。

```bash
python -m venv venv
source venv/bin/activate  # Windowsの場合は venv\Scripts\activate
```

Djangoをインストールします。

```bash
pip install django
```

プロジェクトを作成します。

```bash
django-admin startproject myapp .
```

#### 1-2. アプリの作成

アプリ`bbs`を作成します。

```bash
python manage.py startapp bbs
```

作成したアプリを`myapp/settings.py`の`INSTALLED_APPS`に追加します。

```settings.py
INSTALLED_APPS = [
    ...
    'bbs',
]
```

#### 1-3. プロジェクトの構造の確認
下記のような構造になっていたらok
``` tree
django_app/
├── manage.py
├── myapp/
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── bbs/
    ├── __init__.py
    ├── models.py
    └── ...
```
:::note warn
できていない場合、[1-1](#1-1-プロジェクトのセットアップ)、[1-2](#1-2-アプリの作成)が正しく実行されていない可能性があります。
:::

---

### 2. モデルの作成
#### 2-1. `Article`モデルを定義
`bbs/models.py`に下記を追加します。
```models.py
from django.db import models

class Article(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

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

#### 2-2. モデルを定義したら、マイグレーションを実行。
下記のコマンドをターミナルで実行します。 
```bash
python manage.py makemigrations
python manage.py migrate
```

#### 2-3. データベースで確認
[phpMyAdmin](http://localhost:8888/phpMyAdmin5/)で`bbs_article`が追加されているか確認します。

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3963294/a1a89cc1-eca2-7f74-d6c5-fd80f1dc0136.png">

---

### 3. 管理画面の設定

#### 3-1. 管理画面でモデルを管理できるようにする。
`bbs/admin.py`に以下を記述します。

```admin.py
from django.contrib import admin
from .models import Article

admin.site.register(Article)
```

開発用サーバーを起動し、Django管理画面にアクセスしてモデルを確認します。

```bash
python manage.py runserver
```
::: note info
管理画面は[`http://127.0.0.1:8000/admin/`](http://127.0.0.1:8000/admin/)で開きます。
:::
---

### 4. ビューとURLの設定

#### 4-1. ビューの作成
`bbs/views.py`に以下を記述します。

```bbs/views.py
from django.shortcuts import render
from .models import Article


def index(request):
    articles = Article.objects.all()
    return render(request, 'bbs/index.html', {'articles': articles})
```

#### 4-2. URLパターンの設定
`bbs/urls.py`を作成し、以下を記述します。

```bbs/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
]
```

`myapp/urls.py`にアプリのURLを含めるように設定します。

```myapp/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('bbs.urls')),
]
```

---

### 5. テンプレートの作成

`bbs/templates/bbs/index.html`を作成し、以下を記述します。

```index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>掲示板</title>
</head>
<body>
    <h1>BBS掲示板</h1>
    <a href="{% url 'create' %}">新規投稿</a>
    <ul style="list-style: none;">
        {% for article in articles %}
            <li>
                <h2>{{ article.title }}</h2>
                <p>{{ article.content }}</p>
                <small>{{ article.created_at }}</small>
                <a href="{% url 'edit' article.id %}">編集</a>
                <a href="{% url 'delete' article.id %}">削除</a>
            </li>
        {% endfor %}
    </ul>
</body>
</html>
```

---

### 6. 新規登録機能の追加

#### 6-1. フォームを作成
bbs/forms.pyを作成し、以下を記述します。
```bbs/forms.py
from django import forms
from .models import Article

class ArticleForm(forms.ModelForm):
    class Meta:
        model = Article
        fields = ['title', 'content']
```
#### 6-2. ビューを更新
bbs/views.pyに以下を追加します。
```views.py
from django.shortcuts import redirect
from .forms import ArticleForm

def create(request):
    if request.method == 'POST':
        form = ArticleForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('index')
    else:
        form = ArticleForm()
    return render(request, 'bbs/create.html', {'form': form})
```
#### 6-3. URLを設定
`bbs/urls.py`に以下を追加します。
```bbs/urls.py
urlpatterns = [
    path('', views.index, name='index'),
    path('create/', views.create, name='create'),
]
```
#### 6-4. テンプレートを作成
`bbs/templates/bbs/create.html`を作成し、以下を記述します。
```bbs/templates/bbs/create.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>新規登録</title>
</head>
<body>
    <h1>新規登録</h1>
    <form method="post">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit">登録</button>
    </form>
    <a href="{% url 'index' %}">戻る</a>
</body>
</html>
```
---

### 7. 編集機能の追加

#### 7-1. ビューの追加
bbs/views.pyに以下を追加します。
```views.py
from django.shortcuts import get_object_or_404

def edit(request, article_id):
    article = get_object_or_404(Article, id=article_id)
    if request.method == 'POST':
        form = ArticleForm(request.POST, instance=article)
        if form.is_valid():
            form.save()
            return redirect('index')
    else:
        form = ArticleForm(instance=article)
    return render(request, 'bbs/edit.html', {'form': form})
```
#### 7-2. URLの追加
bbs/urls.pyに以下を追加します。
```bbs/urls.py
urlpatterns = [
    path('', views.index, name='index'),
    path('create/', views.create, name='create'),
    path('edit/<int:article_id>/', views.edit, name='edit'),
]
```
#### 7-3. テンプレートを作成
bbs/templates/bbs/edit.htmlを作成し、以下を記述します。
```bbs/templates/bbs/edit.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>編集</title>
</head>
<body>
    <h1>編集</h1>
    <form method="post">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit">更新</button>
    </form>
    <a href="{% url 'index' %}">戻る</a>
</body>
</html>
```
### 8. 削除機能の追加

#### 8-1. ビューの追加
bbs/views.pyに以下を追加します。
```views.py
def delete(request, article_id):
    article = get_object_or_404(Article, id=article_id)
    if request.method == 'POST':
        article.delete()
        return redirect('index')
    return render(request, 'bbs/delete.html', {'article': article})
```
#### 8-2. URLの追加
bbs/urls.pyに以下を追加します。
```bbs/urls.py
urlpatterns = [
    path('', views.index, name='index'),
    path('create/', views.create, name='create'),
    path('edit/<int:article_id>/', views.edit, name='edit'),
    path('delete/<int:article_id>/', views.delete, name='delete'),
]
```
#### 8-3. テンプレートを作成
bbs/templates/bbs/delete.htmlを作成し、以下を記述します。
```bbs/templates/bbs/delete.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>削除確認</title>
</head>
<body>
    <h1>削除確認</h1>
    <p>本当に"{{ article.title }}"を削除しますか？</p>
    <form method="post">
        {% csrf_token %}
        <button type="submit">削除</button>
    </form>
    <a href="{% url 'index' %}">戻る</a>
</body>
</html>
```

### 9. 動作確認

#### 9-1. 開発サーバーを起動します。
```bash
python manage.py runserver
```

#### 9-2. ブラウザで確認

ブラウザで[http://127.0.0.1:8000/](http://127.0.0.1:8000/)にアクセスし、掲示板が表示されることを確認します。

---

これで、簡単な掲示板が完成しました！