
【70日目】DjangoのCreateViewとは?_プログラミング学び日記
このnoteは、31歳未経験からエンジニアを目指して勉強していく記録を綴っているものです。現在はAdTechでカスタマーサクセスを担当しつつ、色んなチャンスに恵まれ、CS業務や子育てと並行しながらチャレンジしています。
これからプログラミングを始める方にとってのTipsやモチベアップに繋げられるように頑張りたいと思っています。
--------------------------------------------
本日もチュートリアルで作成したTodoアプリに沿って進めています。
ソースコードはこちらです。
前回の記事はこちら
DjangoのCreateViewとは?
CreateViewはオブジェクトの新規作成フォーム画面の描画およびバリデーションエラー表示の機能を持つクラスです。オブジェクトとはモデルのデータで、本記事では作成したアプリのTodoモデルを利用しています。アプリケーション名もTodoです。

解説に使用する各ファイルのコードは以下です。
## models.py
from django.db import models
# Create your models here.
class Todo(models.Model):
title = models.CharField("タスク名", max_length=30, help_text='【社名】を記載してください')
description = models.TextField("詳細", blank=True, help_text='作成物の対象期間や属性などの詳細を記入してください')
deadline = models.DateField("締切")
def __str__(self):
return self.title
## views.py
from django.views.generic import CreateView
class TodoCreate(CreateView):
model = Todo
fields = "__all__"
success_url = reverse_lazy("list")
## urls.py
from django.urls import path
from .views import TodoCreate
urlpatterns = [
path("create/", TodoCreate.as_view(), name="create"),
]
## todo_form.html
{% extends 'todo/base.html' %}
{% block header %}
<h1>タスクの作成/編集</h1>
{% endblock header %}
{% block content %}
<form action="" method="POST">{% csrf_token %}
<table class="table">
{{ form.as_table }}
</table>
<a class="btn btn-outline-secondary" href="{% url 'list' %}" role="button">戻る</a>
<input class="btn btn-success" type="submit" Value="送信">
</form>
{% endblock content %}
では一つずつ見ていきます。
CreateViewクラスとテンプレートファイル(todo_form.html)はどうやって紐づいてる?
まずはViewとテンプレートファイル(todo_form.html)との紐づきに関してです。ListViewやDetailViewとは少し異なり、デフォルトでは「アプリ名/モデル名_form.html」が設定されています。
これはクラス図にもありますが、CreateViewは「template_name_suffix」という属性を持っていて、そこで「 '_form'」がデフォルトで定義されているためです。
また、CreateViewを継承したクラスは内部でフォームを作成しますが、このフォームはコンテキストにformという名前で保存されます。つまり、todo_form.htmlにある通り、forms.as_tableとするとformの内容が表示されます ↓
<table class="table">
{{ form.as_table }}
</table>
fieldsとは?
fieldsはユーザーが投稿画面で入力する項目(フィールド)を指定するものです。つまり、model.pyで定義したデータベースのどのカラムに入力するか指定します。
class TodoCreate(CreateView):
model = Todo
fields = "__all__"
success_url = reverse_lazy("list")
全てのカラムに入力したい場合は、上記のように「"__all__"」を指定します。1つずつ指定する場合は以下のようにPythonのリストとして書きます。
class TodoCreate(CreateView):
model = Todo
fields = ['title', 'description', 'deadline']
success_url = reverse_lazy("list")
success_urlとget_success_url()メソッドの違いは?
success_urlもget_succes_urlも、投稿完了時に遷移するページを指定するものです。edit系(CreateView、UpdateView、DeleteView)はデフォルトで「success_url 」属性をNoneで持っており、継承した際はこの属性を定めなければエラーが返ってきます。表題の2つの違いは以下です。
・success_urlは静的ページにしか使えない(ListViewに戻る、等)
・get_success_url()はselfからURLに含まれる変数を取得でき、動的ページに使える(作成したページのDetailViewに飛ぶ、等)
・success_urlはreverse_lazy()としか組み合わせられず、get_success_url()はreverse()でもreverse_lazy()でも組み合わせることができる
コードは以下のようになります。
# 静的なページしか返せない
success_url = reverse_lazy("urls.pyのname")
def get_success_url(self):
return reverse("urls.pyのname",kwargs={"pk":self.kwargs["pk"]})
# もしくは
def get_success_url(self):
return reverse_lazy("urls.pyのname",kwargs={"pk":self.kwargs["pk"]})
success_urlは、urls.pyがロードされる前に走ってしまうらしく、reverse()の遅延評価バージョンであるreverse_lazy()を使う必要があります。遅延評価とは、実際に処理をするのは後回しにする、という意味です。
get_success_urlにある「self.kwargs["pk"]」ですが、DetailViewに飛ぼうした場合、kwargsの所にobjectと記載することで正常に動作しました。
def get_success_url(self):
return reverse_lazy("detail", kwargs={'pk':self.object.pk})
DetailViewではコンテキスト変数に「task」を指定していたので、最初はobjectではなくtaskと入力しましたが、それではエラーになりました。kwargsのままでもエラーで、objectと入力して初めて正常に動作しました。
原因はまだわからないのですが、DetailViewのデフォルトのコンテキスト変数が「object」なので、クラスを定義する際は各クラスのデフォルト名で書かなければいかないのかも?という仮説を立てています。
この辺も分かったらまたまとめたいと思います。
余談ですが、並行してYouTubeのチュートリアルも進めており、Paizaクラウドで作成したアプリを無事にローカル環境でも動かすことができました。
やはり自分で環境構築して動いた時は本当に楽しいですね。
次回は今回の続きで、todo_form.htmlの中身を深堀したいと思います。
・form.as_pとform.as_tableの違いは?
・csrf_tokenとは?
など
次回記事はこちらです↓
参考
これまで修了したコース等
【YouTube動画】
Pythonでウェブサービスを作ろう! #1
テンプレートをマスターしよう! #2
静的ファイルを配信しよう !#3
データベースと接続しよう! #5
【Paiza】
Aランクレベルアップメニュー 24/49問
ループメニュー1 20/20問
ループメニュー2 8/20問
配列メニュー 41/64問
条件分岐メニュー 25/25問
二重ループメニュー 19/19問
配列活用メニュー 26/26問
文字列処理メニュー 30/30問
Bランクレベルアップメニュー 62/62問
Cランクレベルアップメニュー 30/30問
ランクB合格
ランクC合格
【書籍/ブログ】
Django入門 | 初心者でも1時間でWebアプリ(Todoアプリ)を作成するコース
基礎からのMySQL 514/514頁
Web技術の基本 189/189頁 ※2周目中
京大のPython教科書 116/201頁
Pythonデータベースプログラミング 194/194頁
Pythonエンジニアファーストブック読了
【Progate】
Python Ⅰ~Ⅴ
Python アプリ版 コースⅠ~Ⅴ
SQL Ⅰ~ Ⅳ
SQL アプリ版 コースⅢ
HTML&CSS 初級編
【その他】
Pythonの環境構築
VSCodeの環境構築
MySQLの環境構築(MAMP)
Git / GitHubの環境構築