クラスベースビューとforms.pyを使った新規作成画面の作成について
今回はクラスベースビューとforms.pyを使って新規作成画面を作成する
前回:【Django】クラスベースビューで一覧画面を作成【ブログアプリ2】
現在のディレクトリ構成は以下の通り。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
デスクトップ └Blog2 ├app │ ├migrations │ ├__init__.py │ ├admin.py │ ├apps.py │ ├models.py │ ├tests.py │ ├views.py │ ├urls.py ├db.sqlite3 ├config │ ├・・・ │ ├settings.py │ └urls.py ├templates │ ├base.html │ ├index.html │ └list.html ├env_blog2 └manage.py |
クラスベースビューとforms.pyを使った新規作成画面の作成手順
urls.pyの作成
~デスクトップ/Blog2/app/urls.py
1 2 3 4 5 6 7 8 9 10 |
from django.urls import path, include from .views import TopPageView1, TopPageView2, BlogListView, BlogCreateView #[1] app_name = 'blog' urlpatterns = [ path('', TopPageView1.as_view(), name="index1"), path('index/', TopPageView2.as_view(), name="index2"), path('list/', BlogListView.as_view(), name="list"), path('create/', BlogCreateView.as_view(), name="create"), #[2] ] |
[1]views.pyからBlogCreateViewをインポート
BlogCreateViewは未作成なので、次の手順で作成する。
[2]新しいURLパターンを作成
利用者からのリクエストURLが以下と一致した場合に実行されるPath関数を追加。
第二引数はviews.pyのBlogCreateViewをメソッドとして呼び出している。
第三引数はこのURLパターンをcreateと名付けている。
views.pyの編集
~デスクトップ/Blog2/app/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 |
from django.shortcuts import render from django.views.generic import View, TemplateView, ListView, CreateView #[1] from django.urls import reverse_lazy #[2] from .models import Blog from .forms import CreateForm #[3] # Create your views here. class TopPageView1(View): def get(self, request): template_name = 'index.html' return render(request, template_name) class TopPageView2(TemplateView): template_name = 'index.html' class BlogListView(ListView): model = Blog template_name = 'list.html' context_object_name = 'blogs' #[4] class BlogCreateView(CreateView): model = Blog form_class = CreateForm template_name = 'create.html' success_url = reverse_lazy('blog:list') |
[1]CreateViewをインポート
CreateViewはDjangoに元々用意されている汎用ビュークラス。
新規作成に特化している。
[2]reverse_lazyをインポート
reverse_lazyは遅延評価を行う。
必要になるまで実行を待機することで、バックエンドとの通信の回数を下げ、アプリケーションの負荷を減らすことができる。
[3]forms.pyからCreateFormをインポート
forms.pyでは、フォーム、つまりブログ記事の各入力項目をpythonのファイルとして定義している。
forms.pyは未作成なので、次の手順で作成する。
[4]BlogCreateViewクラスを作成
BlogCreateViewクラスはDjangoの汎用ビュークラスであるCreateViewクラスを継承して作成している。
前回のListViewと同じで、CreateViewは新規作成に特化しているので、変数modelにBlogモデル、template_nameにcreate.htmlのアドレスを、登録が完了した際に一覧画面にリダイレクトするためにsuccess_urlにreverse_lazyで実行を待機させつつ、一覧画面のURLパターンを格納している。
forms.py
~デスクトップ/Blog2/app/forms.py
1 2 3 4 5 6 7 |
from django import forms from .models import Blog class CreateForm(forms.ModelForm): class Meta: model = Blog fields = ['title', 'content'] |
forms.pyを作成した。
関数ベースでブログを作成したときは、forms.pyは使用していない。
代わりにhtmlファイルに直接フォームを記述した。
フォームを使用するのが新規作成画面と更新画面しかなかったので、htmlファイルにフォームを直接記述してもそれほど大変ではない。
ただ、フォームを使用する画面が増えてきたら、それぞれのhtmlファイルに記述するのは負荷が大きい。
そこで、forms.pyを使用することでフォームの記述場所を一か所に集約して管理しやすくすることができる。
また、models.pyで定義したモデルが持つフィールドから自動でフォームを作成することができるので、htmlファイルに直接フォームを定義していくよりも楽にフォームを作成することができる。
from django import forms
djangoからformsをインポート。後述のModelFormが定義されている。
from .models import Blog
models.pyからBlogモデルをインポート。
Blogモデルが持つ各フィールド(title, content)から自動でフォームを作成するため、Blogモデルをインポートしている。
class CreateForm(forms.ModelForm):
class Meta:
model = Blog
fields = [‘title’, ‘content’]
CreateFormクラスを定義している。
CreateFormクラスはdjangoのformsモジュール内のModelFormクラスを継承して作成している。
さらに内部にMetaクラスを作成し、変数modelにBlogモデルを格納し、fieldsにBlogモデルのフィールドであるtitleとcontentをリスト形式で指定した。
これにより、Blogモデルで定義したtitle, contentフィールドが自動でフォームとして作成することができる。
ちなみにBlogモデルにはcreated_dateフィールドがあるが、これはオプションでauto_now_add=Trueとしており、ブログ記事が新規作成された時に自動で’作成日’が作られるのでfieldsに入れる必要がない。というよりも入れることができない。auto_now_add=Falseとすることでfieldsにcreate_dateを含めることはできる。
create.htmlの作成
~デスクトップ/Blog2/template/list.html
1 2 3 4 5 6 7 8 9 10 11 12 |
{% extends 'base.html' %} {% block title %}ブログ{% endblock %} {% block content%} <h1>新規作成</h1> <form method="post"> {% csrf_token %} {{ form.as_p }} <button type="submit">登録</button> </form> {% endblock %} |
<form method=”post”>
POSTメソッドでフォーム作成を指示している。
{% csrf_token %}
csrf_tokenを記述。おまじないのようなものでコピペで書いても良い。
セキュリティ上必要なため、これがないとエラーになる。
このテンプレートタグを記述するだけでクロスサイトリクエストフォージェリ対策を行っている。
{{ form.as_p }}
formオブジェクトは、ModelFormを継承して作成された
<button type=”submit”>登録</button>
登録ボタンを作成。
</form>
POSTメソッドで使用するフォームをここで終了する。
ディレクトリ構成の確認
現在のディレクトリ構成は以下の通り。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
デスクトップ └Blog2 ├app │ ├migrations │ ├__init__.py │ ├admin.py │ ├apps.py │ ├models.py │ ├tests.py │ ├views.py #編集 │ ├urls.py #編集 │ └forms.py #新規作成 ├db.sqlite3 ├config │ ├・・・ │ ├settings.py │ └urls.py ├templates │ ├base.html │ ├index.html │ ├list.html │ └create.html #新規作成 ├env_blog2 └manage.py |
urls.pyでは新しいURLパターンを作成した。
利用者からのリクエストのURLが以下と一致した場合に実行されるPath関数を追記している。
views.pyでは汎用ビュークラスのCreateViewを継承したBlogCreateViewを作成した。
forms.pyではModelFormクラスを継承したCreateFormクラスを作成した。CreateFormクラスはBlogモデルから適切なフォームを自動で作成することができる。
create.htmlではCreateFormクラスで作成した各フォームをviews.pyを通して受け取り、htmlのpタグとして表示している。
また、それらのフォームを登録ボタンを押すことでPOSTメソッドとしてアプリケーションに送信することができる。
Django記事一覧
前回:【Django】クラスベースビューで一覧画面を作成【ブログアプリ2】
次回:【Django】クラスベースビューで詳細画面を作成【ブログアプリ2】
コメント