超初心者用: Djangoでウェブアプリを作る ⑥ユーザーによるentryの編集

前回に引き続き、今回もユーザーによるデータの変更に対応していきます。今回はユーザー自身が entry を編集できるようにします。

Entry の編集

edit_entry URL

entry を編集するURLには id が必要になります。practicing_logs/urls.py はこんな感じになります。

# practicing_logs/urls.py

#--省略--
urlpatterns = [
    #--省略--
    #  entry を編集するためのページ
    url(r'^edit_entry/(?P<entry_id>\d+)/$', views.edit_entry, name='edit_entry'),
]

もうこりごりするほどこの形式を見てきましたね。 http://localhost:8000/edit_entry/1/ のリンクで entry_id が1の entry を編集できるページに飛びます。URLがそれとマッチするときedit_entry() の view function が呼ばれます。

edit_entry() view function

GET リクエストを edit_entry ページが受け取ったとき、 edit_entry() が entry を変更するためのフォームを返します。POST リクエストを受け取ったときは、修正された文章をデータベースに保存します。

#views.py

from django.shortcuts import render
#--省略--
from .models import Topic, Entry   #<----ここ
from .forms import TopicForm, EntryForm
#--省略--


def edit_entry(request, entry_id):
    """すでにある entry の編集"""
    entry = Entry.objects.get(id=entry_id)
    topic = entry.topic
    
    if request.method != 'POST':
        # 何も変更がない時
        form = EntryForm(instance=entry)
    else:
        # POST データが送信されたとき
        form = EntryForm(instance=entry, data=request.POST)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect(reverse('practicing_logs:topic', args=[topic.id]))

    context = {'entry': entry, 'topic': topic, 'form': form}
    return render(request, 'practicing_logs/edit_entry.html', context)

まずは Entry モデルをインポートしなければなりません。

entry = Entry.objects.get(id=entry_id)

ユーザーが編集する entry を entry_id を使って入手します。

if request.method != 'POST':

もしリクエストがPOST以外であるならば、現在の entry の内容を持った EntryForm を作成します。つまり同じ内容を上書きする感じです。

form = EntryForm(instance=entry, data=request.POST)

リクエストがPOSTだった場合は、instance=entry と data=request.POST を送ります。これはPOSTのリクエストからのユーザーが入力した文章で form instance を作ります。そのあと整合性をチェックし、合格すれば save() を行ってデータベースに保存します。最後にはトピックページにリダイレクトします。

edit_entry template

# edit_entry

{% extends "practicing_logs/base.html" %}
{% block content %}
<p><a href="{% url 'practicing_logs:topic' topic.id %}">{{ topic }}</a></p>

<p>Edit entry:</p>

<form action="{% url 'practicing_logs:edit_entry' entry.id %}" method='post'>
    {% csrf_token %}
    {{ form.as_p }}
    <button name="submit">save changes</button>
</form>
{% endblock content %}

action argument はedit_entry() にフォームを送ります。そして view function が entry を編集します。

edit_entry ページをリンクする

edit_entry ページをそれぞれの entry から飛べるようにします。

#topic.html

#--省略--
{% for entry in entries %}
    <li>
        <p>{{ entry.date_added | date: 'M d, Y H:i' }}</p>
        <p>{{ entry.text | linebreakes }}</p>
        <p>
            <a href="{% url 'practicing_logs:edit_entry' entry.id %}">edit entry</a>
        </p>
    </li>
#--省略--

それぞれの entry の本文の下に edit ページへのリンクを設置しました。entry id でどの entry を編集するかを識別しています。見た目はこんな感じです。

f:id:kendamaaa:20200428153830j:plain

次回

次はユーザーそれぞれにアカウントを与えて、トピックと entry を管理していきます。