Django開発 ~ブログ構築編1~の続きです。
<目次>
投稿フォームの実装
ブログの投稿フォームを実装しようと思います。
django では、慣習的に「forms.py」にフォームを実装することになっています。デフォルトでは作成されないので、まずはforms.pyを作成してみましょう。
1 |
touch app/blog/forms.py |
続いて、このフォームの中身を書いていきます。
1 2 3 4 5 6 7 8 9 10 11 |
vi app/blog/forms.py from django import forms from .models import Post class PostForm(forms.ModelForm): class Meta: model = Post fields = ('title', 'body', 'status', 'author') |
「class Meta」 には、紐づけたいDjangoモデルを指定できるので、前回作成した「Postモデル」に紐づける設定を行いました。これでこのformは、Postモデルに関連するフォームになるわけです。
「fields」には、フォームの入力フィールドを設定できます。今回は、タイトル、ボディ、ステータス、投稿者の4つを指定しておきます。
投稿Viewの作成
投稿Viewを作成してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
vi app/blog/views.py from django.contrib.auth import get_user_model # new from django.views.generic import CreateView, UpdateView # new from django.shortcuts import render, get_object_or_404, redirect #new from .models import Post from .forms import PostForm # new def post_list(request): posts = Post.published.all() return render(request, 'blog/post/list.html', {'posts': posts}) def post_detail(request, year, month, day, post): """Show post datail""" post = get_object_or_404(Post, slug=post, status='published', publish__year=year, publish__month=month, publish__day=day) return render(request, 'blog/post/detail.html', {'post': post}) # new class PostCreateView(CreateView): model = Post form_class = PostForm form_class.author = get_user_model() template_name = 'blog/post/form.html' success_url = '/blog' def form_valid(self, form): self.object = form.save(False) self.object.slug = (form.cleaned_data['title']).replace(' ', '-') self.object.save() return redirect('blog:post_list') |
前回定義したView(post_list, post_detail)とは違って、今回追加したViewは、Djangoのクラスベース汎用ビューという機能を継承して作成しています。
URLの追加
新しいViewを追加したので、urls.pyに登録します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
vi app/blog/urls.py from django.urls import path from . import views # application name space app_name = 'blog' urlpatterns = [ path('', views.post_list, name='post_list'), path('<int:year>/<int:month>/<int:day>/<slug:post>/', views.post_detail, name='post_detail'), path('create/', views.PostCreateView.as_view(), name='create'), # new ] |
form テンプレートの作成
tempaltes/blog/post 配下に form.html を作成しましょう。
1 |
touch app/blog/templates/blog/post/form.html |
HTMLを記載します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
vi app/blog/templates/blog/post/form.html {% extends "blog/base.html" %} {% block content %} <form method="post"> {% csrf_token %} {{ form }} <button type="submit">save</button> </form> {% endblock %} |
list.htmlに投稿ボタンを設置しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
vi app/blog/templates/blog/post/list.html {% extends "blog/base.html" %} {% block title %}My Blog{% endblock %} {% block content %} <a href="{% url 'blog:create' %}">POST</a> <h1>My Blog</h1> {% for post in posts %} <h2> <a href="{{ post.get_absolute_url }}"> {{ post.title }} </a> </h2> <p class="date"> Published {{ post.publish }} by {{ post.author }} </p> {{ post.body|truncatewords:30|linebreaks }} {% endfor %} {% endblock %} |
ここまで作業を終えたら一旦、「localhost:8000/blog」にアクセスして、画面を確認してみましょう。



デザインはともかく、だんだんブログっぽくなってきましたね。スタイル(CSS)は、後で直しましょう^^
投稿の更新
投稿した内容を更新できるようにしましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
vi app/blog/views.py from django.contrib.auth import get_user_model from django.views.generic import CreateView, UpdateView from django.shortcuts import render, get_object_or_404, redirect from .models import Post from .forms import PostForm def post_list(request): posts = Post.published.all() return render(request, 'blog/post/list.html', {'posts': posts}) def post_detail(request, year, month, day, post): """Show post datail""" post = get_object_or_404(Post, slug=post, status='published', publish__year=year, publish__month=month, publish__day=day) return render(request, 'blog/post/detail.html', {'post': post}) class PostCreateView(CreateView): model = Post form_class = PostForm form_class.author = get_user_model() template_name = 'blog/post/form.html' success_url = '/blog' def form_valid(self, form): self.object = form.save(False) self.object.slug = (form.cleaned_data['title']).replace(' ', '-') self.object.save() return redirect('blog:post_list') # new class PostUpdateView(UpdateView): model = Post form_class = PostForm form_class.author = get_user_model() template_name = 'blog/post/form.html' success_url = '/blog' def form_valid(self, form): self.object = form.save(False) self.object.slug = (form.cleaned_data['title']).replace(' ', '-') self.object.save() return redirect('blog:post_list') |
urls.py も編集します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
vi app/blog/urls.py from django.urls import path from . import views # application name space app_name = 'blog' urlpatterns = [ path('', views.post_list, name='post_list'), path('<int:year>/<int:month>/<int:day>/<slug:post>/', views.post_detail, name='post_detail'), path('create/', views.PostCreateView.as_view(), name='create'), # new path('update/<int:pk>/', views.PostUpdateView.as_view(), name='update'), ] |
list.html にリンクを追加してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
vi app/blog/templates/blog/post/list.html {% extends "blog/base.html" %} {% block title %}My Blog{% endblock %} {% block content %} <a href="{% url 'blog:create' %}">POST</a> <h1>My Blog</h1> {% for post in posts %} <h2> <a href="{{ post.get_absolute_url }}"> {{ post.title }} </a> </h2> <p class="date"> Published {{ post.publish }} by {{ post.author }} </p> {{ post.body|truncatewords:30|linebreaks }} <!-- new --> <p class="update"> <a href="{% url 'blog:update' post.id %}">Update</a> </p> {% endfor %} {% endblock %} |
ついでに詳細画面に遷移した後、トップページに戻るボタンを追加しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
vi app/blog/templates/blog/post/detail.html {% extends "blog/base.html" %} {% block title%}{{ post.title }}{% endblock %} {% block content %} <h1>{{ post.title }}</h1> <p class="date"> Published {{ post.publish }} by {{ post.author }} </p> {{ post.body|linebreaks }} <p><a href="{% url 'blog:post_list' %}">TOP</a></p> {% endblock %} |



更新画面は問題なさそうですね。よりブログらしくなりました。
投稿の削除
最後に投稿を削除できるようにしましょう。
まずは、views.pyを編集します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
vi app/blog/views.py from django.contrib.auth import get_user_model from django.views.generic import CreateView, UpdateView, DeleteView # new from django.shortcuts import render, get_object_or_404, redirect from .models import Post from .forms import PostForm def post_list(request): posts = Post.published.all() return render(request, 'blog/post/list.html', {'posts': posts}) def post_detail(request, year, month, day, post): """Show post datail""" post = get_object_or_404(Post, slug=post, status='published', publish__year=year, publish__month=month, publish__day=day) return render(request, 'blog/post/detail.html', {'post': post}) class PostCreateView(CreateView): model = Post form_class = PostForm form_class.author = get_user_model() template_name = 'blog/post/form.html' success_url = '/blog' def form_valid(self, form): self.object = form.save(False) self.object.slug = (form.cleaned_data['title']).replace(' ', '-') self.object.save() return redirect('blog:post_list') class PostUpdateView(UpdateView): model = Post form_class = PostForm form_class.author = get_user_model() template_name = 'blog/post/form.html' success_url = '/blog' def form_valid(self, form): self.object = form.save(False) self.object.slug = (form.cleaned_data['title']).replace(' ', '-') self.object.save() return redirect('blog:post_list') # new class PostDeleteView(DeleteView): model = Post form_class = PostForm template_name = 'blog/post/post_confirm_delete.html' success_url = '/blog' |
続いて、urls.py を編集します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
vi app/blog/urls.py from django.urls import path from . import views # application name space app_name = 'blog' urlpatterns = [ path('', views.post_list, name='post_list'), path('<int:year>/<int:month>/<int:day>/<slug:post>/', views.post_detail, name='post_detail'), path('create/', views.PostCreateView.as_view(), name='create'), path('update/<int:pk>/', views.PostUpdateView.as_view(), name='update'), path('delete/<int:pk>/', views.PostDeleteView.as_view(), name='delete'), # new ] |
DeleteViewクラスを継承したViewを実装すると削除確認フォームを作成する必要があります。
1 |
touch app/blog/templates/blog/post/post_confirm_delete.html |
中身を描いてみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
vi app/blog/templates/blog/post/post_confirm_delete.html {% extends "blog/base.html" %} {% block title %}Confirm Form{% endblock %} {% block content %} <p>Will you delete {{ object }} ?</p> <form method="post"> <button>DELETE</button> {% csrf_token %} </form> {% endblock %} |
続いて、list.htmlを編集します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
vi app/blog/templates/blog/post/list.html {% extends "blog/base.html" %} {% block title %}My Blog{% endblock %} {% block content %} <a href="{% url 'blog:create' %}">POST</a> <h1>My Blog</h1> {% for post in posts %} <h2> <a href="{{ post.get_absolute_url }}"> {{ post.title }} </a> </h2> <p class="date"> Published {{ post.publish }} by {{ post.author }} </p> {{ post.body|truncatewords:30|linebreaks }} <p class="update"> <a href="{% url 'blog:update' post.id %}">Update</a> </p> <p class="delete"> <a href="{% url 'blog:delete' post.id %}">Delete</a> <!-- new --> </p> {% endfor %} {% endblock %} |
これで削除機能は完了です。動作確認をしてみましょう。



おわりに
だんだんとブログに近づいてきました。
次は、ブログにスタイル(BootStrap,CSS)を追加しましょう^^
コメントを残す
コメントを投稿するにはログインしてください。