
Djangoで1行掲示板にユーザーが投稿するための新規投稿機能を作ってみましょう。新規投稿機能を作成するには投稿フォームとそれを表示するWebページ、投稿内容をデータベースに保存するなど複数の機能が必要になります。
目次
- 必要な機能のリストアップ
- ルーティング
- 新規投稿ページへ遷移するためのボタンをindex.htmlに配置
- 新規投稿フォームを定義
- 新規投稿ページを呼び出すための関数を作成
- 投稿用Webページ(new.html)の作成
- 投稿内容をデータベースに保存する関数を作成
- 投稿完了ページ(posted.html)を作成
- 動作確認
必要な機能のリストアップ
まずはじめに必要になる機能とページを確認しておきましょう。
掲示板の新規投稿には次の各機能が必要となります。

- 投稿用Webページ、投稿保存機能へのルーティング(urls.pyに記述)
- 新規投稿ページへ遷移するためのボタン(index.htmlに配置)
- 新規投稿用のWebページ(new.htmlを作成)
- 投稿内容をデータベースに保存する関数(views.pyに記述)
- 投稿完了ページ(posted.html)を作成
これらを1つずつ作っていきましょう。
ルーティング
まずはユーザーが各URLにアクセスした場合のルーティング処理を作成します。
/bbs/urls.py に次のように記述します。
from django.urls import path
from . import views
app_name = 'bbs'
urlpatterns = [
path('', views.index, name='index'),
path('<int:id>', views.detail, name='detail'),
path('new', views.new, name='new'), # 投稿用WebページのURL
path('create', views.create, name='create'), # 新規投稿をデータベースに保存するためのURL
]
ユーザーが /bbs/new/ にアクセスすると views.py の new関数を、/bbs/create/ にアクセスすると views.py の create関数を呼び出します。
また、それぞれname属性を付けておいたので、newやnameといった名前でこのURLをリンクで呼び出せます。
新規投稿ページへ遷移するためのボタンをindex.htmlに配置
投稿一覧ページに新規投稿ページへの遷移ボタンを配置しておきましょう。
{% extends "./base.html" %}
{% block content %}
<h1>Djangoで作る1行掲示板</h1>
{% if searchForm %}
<form action='{% url "bbs:index" %}' method="get">
<div>
{{ searchForm }}
<input type="submit" value="検索">
<a href='{% url "bbs:index" %}'>クリア</a>
</div>
</form>
{% endif %}
{% for article in articles %}
<p>
<a href='{% url "bbs:detail" article.id %}'>{{ article.content }}</a>
{{ article.user_name }}
</p>
{% endfor %}
<!-- 新規投稿ページへの遷移ボタン -->
<p>
<button onclick='location.href="{% url "bbs:new" %}"'>新規投稿</button>
</p>
{% endblock %}
先ほど urls.py で /new/ のURLを new という名前で呼び出せるようにしておいたので、25行目のリンクで /bbs/new/ へ遷移することができます。
新規投稿フォームを定義
次に新規投稿フォームを定義しましょう。
forms.py に次のように記述します。
from django import forms
from .models import Article # models.pyからArticleクラスをインポート
# SearchFormクラスを定義
class SearchForm(forms.Form):
keyword = forms.CharField(label='', max_length=50)
# 新規投稿フォームを定義
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = ('content', 'user_name')
データベースに書き込むためのフォームなので、データ形式を指定する時にモデルを参照するだけで記述できます。
新規投稿ページを呼び出すための関数を作成
作成したフォームを利用して新規投稿用のWebページを呼び出すための関数を作成します。
views.py に次のように記述します。
from django.shortcuts import render,get_object_or_404
from django.http import HttpResponse
from .models import Article
from .forms import SearchForm
from .forms import ArticleForm # forms.pyからArticleFormクラスをインポート
def index(request):
searchForm = SearchForm(request.GET)
if searchForm.is_valid():
keyword = searchForm.cleaned_data['keyword']
articles = Article.objects.filter(content__contains=keyword)
else:
searchForm = SearchForm()
articles = Article.objects.all()
context = {
'articles': articles,
'searchForm': searchForm,
}
return render(request, 'bbs/index.html', context)
def detail(request, id):
article = get_object_or_404(Article, pk=id)
context = {
'article': article,
}
return render(request, 'bbs/detail.html', context)
# 新規投稿画面のWebページを返すnew関数
def new(request):
articleForm = ArticleForm() # ArticleFormオブジェクトを生成
# テンプレート側でarticleFormのデータを取り出せるようにcontextに渡す
context = {
'articleForm': articleForm,
}
return render(request, 'bbs/new.html', context) # new.htmlというテンプレートを返す
新規投稿フォームを呼び出すだけなので
- forms.pyからArticleFormクラスをインポート
- articleFormオブジェクトを用意してcontextに追加
- テンプレート(new.html)を呼び出す
これだけです。
投稿用Webページ(new.html)の作成
views.py で呼び出すように記述した new.html というテンプレートファイルを作成します。
/templates/bbs/ に new.html という名前でファイルを作成し、次のように記述します。
{% extends "./base.html" %}
{% block content %}
<h1>Djangoで作る新規投稿フォーム</h1>
<form action='{% url "bbs:create" %}' method="post">
{% csrf_token %}<!-- セキュリティのための記述 -->
{{ articleForm }}<!-- views.pyから受け取ったarticleFormを表示 -->
<button type='submit'>投稿</button>
<a href='{% url "bbs:index" %}'>一覧ページへ戻る</a>
</form>
{% endblock %}
forms.py で定義した ArticleForm クラスを元に、views.py の new関数の中でオブジェクトを作成してテンプレートに渡しているので、テンプレート側では articleForm という変数名を指定するだけで、必要な項目(今回はcontentとUser name)が用意されたフォームを作成してくれます。
また、6行目では「投稿」ボタンをクリックすると create という名前のルートをPOSTメソッドで呼び出すよう記述しています。
※csrf_tokenはDjangoが用意してくれているセキュリティ機能です。フォームがデータを送信する時にトークン情報を一緒に送信し、リクエストを受け取ったViewが、トークンが正しいものがどうか検証し、正常なリクエストだと認められれば処理を実行してくれます。
投稿内容をデータベースに保存する関数を作成
次に、投稿用Webページで「投稿」ボタンを押した時に呼び出される create関数を作成しましょう。
views.py に次のように記述します。
from django.shortcuts import render,get_object_or_404
from django.http import HttpResponse
from .models import Article
from .forms import SearchForm
from .forms import ArticleForm # forms.pyからArticleFormクラスをインポート
def index(request):
searchForm = SearchForm(request.GET)
if searchForm.is_valid():
keyword = searchForm.cleaned_data['keyword']
articles = Article.objects.filter(content__contains=keyword)
else:
searchForm = SearchForm()
articles = Article.objects.all()
context = {
'articles': articles,
'searchForm': searchForm,
}
return render(request, 'bbs/index.html', context)
def detail(request, id):
article = get_object_or_404(Article, pk=id)
context = {
'article': article,
}
return render(request, 'bbs/detail.html', context)
# 新規投稿画面のWebページを返すnew関数
def new(request):
articleForm = ArticleForm()
context = {
'articleForm': articleForm,
}
return render(request, 'bbs/new.html', context)
#新規投稿データを保存するcreate関数
def create(request):
# リクエストのメソッドがPOSTなら
if request.method == 'POST':
articleForm = ArticleForm(request.POST) # リクエストから取り出したデータを代入
# 受け取ったデータが正常なら
if articleForm.is_valid():
article = articleForm.save() # データを保存
context = {
'article': article,
}
return render(request, 'bbs/posted.html', context) # detail.htmlを返す
この関数は新規投稿フォームからデータを受け取った時、POSTメソッドかどうか、受け取ったデータが正常かどうかをチェックし、問題なければデータを保存します。
その後、保存したデータを context に追加して、テンプレートファイル(posted.html)を呼び出します。
投稿完了ページ(posted.html)を作成
最後に、ユーザーに投稿完了を知らせる投稿完了ページのテンプレートを作成しましょう。
/templates/bbs/ に posted.html という名前でファイルを作成し、次のように記述します。
{% extends "./base.html" %}
{% block content %}
<h1>{{ article.id }}の投稿が完了しました!</h1>
<p>{{ article.content }}, {{article.user_name }}</p>
<p><a href='{% url "bbs:index" %}'>一覧ページへ戻る</a></p>
{% endblock %}
投稿した記事のidと投稿内容、投稿者名、そして一覧ページに戻るためのリンクを配置しています。
動作確認
それでは動作確認です。
Djangoコマンドを使ってサーバーを起動し、ブラウザで確認してみましょう。
http://127.0.0.1:8000/bbs にアクセスします。

新規投稿ボタンをクリックしてみましょう。
このように新規投稿フォームが表示されます。
※一切ページデザインをしていないのでガタガタですが、見た目は後からいくらでも整えることができます。
試しにデータを入力して「投稿」してみましょう。
「投稿」ボタンをクリック
投稿完了ページへと遷移しました。
※何度かテストしたのでidがずれてしまっています。気にしないで下さい。
「一覧ページへ戻る」をクリックしてみましょう。
先ほど投稿した内容が一覧ページにも反映されています。
新規投稿機能の完成です!







