Djangoでフォーム操作(データの作成・編集・削除を行う)

この記事ではDjangoでデータを作成・編集・削除を行う手順を紹介します。
簡単なブログアプリを作成して、

「データの作成・保存」
「保存されたデータの編集・更新」
「保存されたデータの削除」

を行います。

作成
ブログ記事を作成し、投稿する。
投稿したデータはデータベースに格納される。
編集
登録されているブログ記事を編集し、更新する。
データベースのデータは更新される。
削除
登録されているブログ記事を削除する。
データベースからデータは消える。

それぞれ決まった手順で作業を行いますので、手順を意識すると覚えやすいかもしれません。

  1. urls.pyにURLパターンを追記する
  2. views.pyにビューのクラスを作成する
  3. テンプレートのHTMLを作成する

なお、Djangoプロジェクトを作るなどの事前準備は一番下の項目に書いています。
検索してきた方が早く答えにたどり着くようにするためです。

CreateViewを利用してデータを作成する

モデルを作ります。
blog/models.pyを編集します。

from django.db import models
from django.urls import reverse

# Create your models here.
class Post(models.Model):
  title = models.CharField(max_length=200)
  author = models.CharField(max_length=30)
  body = models.TextField()


  def __str__(self):
    return self.title

  def get_absolute_url(self):
    return reverse('blog_detail', args=[str(self.id)])

マイグレーションします。

% python manage.py makemigrations blog
% python manage.py migrate blog

ビューを作成します。
blog/views.pyを編集します。

from django.views.generic import ListView, CreateView, DetailView

from .models import Post

# Create your views here.
class BlogListView(ListView):
  model = Post
  template_name = 'home.html'

class BlogDetailView(DetailView):
  model = Post
  template_name = 'blog_detail.html'

class BlogCreateView(CreateView):
  model = Post
  template_name = 'blog_new.html'
  fields = ['title', 'author', 'body']

blog/urls.pyを編集します。

from django.urls import path
from .views import BlogListView, BlogCreateView, BlogDetailView

urlpatterns = [
  path('post/<int:pk>/', BlogDetailView.as_view(), name='blog_detail'), 
  path('', BlogListView.as_view(), name='home'),
  path('post/new/', BlogCreateView.as_view(), name='blog_new'),
]

templates/blog_new.htmlを作成します。


<h1>新しい投稿</h1>
<form action="" method="post">
  {% csrf_token %}
  {{ form.as_p }}
  <input type="submit" value="保存" />
</form>

サーバーを起動します。

% python manage.py runserver 

http://127.0.0.1:8000/post/new/を開くと、登録フォームが表示されます。

データを投稿するとblog_detail.htmlが開きます。
登録したデータが表示されます。

templates/blog_detail.htmlは以下のように書いています。

<div class="post-entry">
  <h2>{{ object.title }}</h2>
  <p>{{ object.body }}</p>
</div>

EditViewを利用してデータを更新する

次にデータの更新をやっていきましょう。

ビューにUpdateViewを追加します。
blog/views.pyを以下のように編集してください。

from django.views.generic import ListView, CreateView, DetailView, UpdateView

from .models import Post

# Create your views here.
class BlogListView(ListView):
  model = Post
  template_name = 'home.html'

class BlogDetailView(DetailView):
  model = Post
  template_name = 'blog_detail.html'

class BlogCreateView(CreateView):
  model = Post
  template_name = 'blog_new.html'
  fields = ['title', 'author', 'body']

class BlogUpdateView(UpdateView):
  model = Post
  template_name = 'blog_edit.html'
  fields = ['author', 'title', 'body']

blog/urls.pyは以下のようにします。

from django.urls import path
from .views import (
  BlogListView, 
  BlogCreateView, 
  BlogDetailView,
  BlogUpdateView,
)

urlpatterns = [
  path('post/<int:pk>/', BlogDetailView.as_view(), name='blog_detail'), 
  path('', BlogListView.as_view(), name='home'),
  path('post/new/', BlogCreateView.as_view(), name='blog_new'),
  path('post/<int:pk>/edit/', BlogUpdateView.as_view(), name='blog_edit'),
]

templates/blog_edit.htmlは以下のようにします。

<h1>記事を編集する</h1>
<form action="" method="post">
  {% csrf_token %}
  {{ form.as_p }}
  <input type="submit" value="更新" />
</form>

http://127.0.0.1:8000/post/1/edit/を開くと、下のような更新ビューが表示されます。

DeleteViewを利用してデータを削除する

最後に登録したデータの削除を行います。

templates_/blog_delete.htmlを以下のように書きます。

<h1>記事を削除する</h1>
<form action="" method="post">
  {% csrf_token %}
  <p>本当に{{ post.title }}を削除してもよろしいですか?</p>
  <input type="submit" value="確認" />
</form>

次にblog/views.pyを以下のように書きます。

from django.views.generic import ListView, CreateView, DetailView, UpdateView, DeleteView
from django.urls import reverse_lazy

from .models import Post

# Create your views here.
class BlogListView(ListView):
  model = Post
  template_name = 'home.html'

class BlogDetailView(DetailView):
  model = Post
  template_name = 'blog_detail.html'

class BlogCreateView(CreateView):
  model = Post
  template_name = 'blog_new.html'
  fields = ['title', 'author', 'body']

class BlogUpdateView(UpdateView):
  model = Post
  template_name = 'blog_edit.html'
  fields = ['author', 'title', 'body']

class BlogDeleteView(DeleteView):
  model = Post
  template_name = 'blog_delete.html'
  success_url = reverse_lazy('home')

blog/urls.pyに削除用のURLを定義します。

from django.urls import path
from .views import (
  BlogListView, 
  BlogCreateView, 
  BlogDetailView,
  BlogUpdateView,
  BlogDeleteView,
)

urlpatterns = [
  path('post/<int:pk>/', BlogDetailView.as_view(), name='blog_detail'), 
  path('', BlogListView.as_view(), name='home'),
  path('post/new/', BlogCreateView.as_view(), name='blog_new'),
  path('post/<int:pk>/edit/', BlogUpdateView.as_view(), name='blog_edit'),
  path('post/<int:pk>/delete/', BlogDeleteView.as_view(), name='blog_delete')
]

削除用URLにリンクするために、template/home.htmlは以下のように編集します。


{% for post in object_list %}
<div class="post">
  <h2>詳細へ:<a href="{% url 'blog_detail' post.pk %}">{{ post.title }}</a></h2>
  <p>{{ post.body }}</p>
  <h2>編集:<a href="{% url 'blog_edit' post.pk %}">{{ post.title }}</a></h2>
  <h2>削除:<a href="{% url 'blog_delete' post.pk %}">{{ post.title }}</a></h2>
</div>
{% endfor %}

ホーム画面はこうなります(ごちゃごちゃしてますが、サンプルなので気にしないでください)

削除のリンクに飛ぶと、削除確認画面が出てきます。
確認を押すと記事を削除できます。

Djangoプロジェクトの準備をする

Djangoプロジェクトの準備をどうやってしたかを説明します。
プロジェクトを作成する手順は別の記事で詳しく書いているので、ここではコマンドだけを書き残します。

% mkdir blogexample; cd blogexample
% pipenv install django==3.0.3
% pipenv shell
% django-admin startproject blogexample .
pipenvを使ってDjangoプロジェクトを作成する

Djangoアプリケーションは以下のコマンドで作成します。

% python manage.py startapp blog

blogexample/settings.pyのINSTALLED_APPSに上記で作成したblogアプリケーションを追加します。

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog.apps.BlogConfig', # new
]

blogexample/urls.pyにアプリケーションのurls.pyを読み込むように定義を追加します。

from django.contrib import admin
from django.urls import path, include # new

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('blog.urls')), # new
]

blog/urls.pyを作成し、以下のように書きます。

from django.urls import path
from .views import BlogListView, BlogCreateView

urlpatterns = [
  path('', BlogListView.as_view(), name='home'),
  path('', BlogCreateView.as_view(), name='new'),
]

プロジェクトのルートディレクトリに「templates」ディレクトリを作ります。

templates以下のテンプレートを読み込む設定をします。
blogexamples/settings.pyのTEMPLATESを以下のように編集します。
変更したのはDIRSです。


TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

templates/home.htmlに以下のように書きます。


{% for post in object_list %}
<div class="post">
  <h2><a href="{% url 'blog_edit' post.pk %}">{{ post.title }}</a></h2>
  <p>{{ post.body }}</p>
</div>
{% endfor %}

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です