Djangoの学習 モデルフォームの使い方
フォームには2つタイプがある。
一つは、django.forms.Formクラスを継承したやり方。
これは、forms.pyに直接フォームの定義を記載する。
直接記載するので、forms.pyに定義づけは必要だけど、データベースとは関係なので、モデルファイルは作らなくてもOKなやり方。
もう一つは、django.forms.ModelFormクラスを継承したやり方。
これば、models.pyに定義を記載して、それを元にフォームを設定するやり方。
これは、モデルクラスを作ってからそれを利用するやり方。
フォームへの書き方はカラム名を書くだけで、シンプルだけど、データベースの設定やモデルファイルを作成する必要がある。
ちなみに、関数ベースをまとめた記事はこちらです。
どんなフォームにするか決める
今回はモデルベースのフォームを使う。
そうなると、データベースの設定をしないといけない。
簡単にイメージをまとめる。
※イメージ
顧客情報を登録して表示したい。
最初から難しいことは出来ないので
・顧客情報を登録
・顧客一覧が表示される
という2点に絞る。
また、デザインは全く無視する方向性でやってみる。
本当は、顧客登録をして、検索してヒットしたら表示、ヒットしなかったら、「ありません」と表示し、顧客情報の編集、削除などもやりたい。また、ログインしている人だけが入れるようにしたりと、やりたいことはまだまだあるけど、まずは、登録して表示できる状態にしたい。
登録から表示までの手順
まずは手順をイメージして書きだす
1.models.pyにテーブル情報設定
2.データベースに反映させる(マイグレーション)
3.頭を一度整理する
4.urls.pyにurlを追加する
5.forms.pyにフォーム内容を記載する
6.views.pyに表示関係を記載する
7.htmlファイルを編集する
まだ解説していない手順も途中で出てくるが、作ってから記事を書いているため仕方ない。それよりも、今これをこういう風に書いたら、他にどんな影響が出るか?というのをその場で解説をしたいため、少し順不同で記載している。そういう時は、
と表記するようにしている。
では早速手順1から確認していく。
1.models.pyにテーブル情報を設定する
models.pyにテーブル情報を記載する。
場所
project_name > app_name > models.py
from django.db import models # Create your models here. class Customer(models.Model): name = models.CharField(max_length=255) def __str__(self): return self.name
Customerというテーブルに、nameというカラム名がありますよ。という意味。
一番下に書いてある、これは何か?
しっかりと説明は出来ないけど、付けるのがデフォっぽい。各サイトの説明文は読んだけど、いまいちピンとこなかった。なんでつけなきゃいけないのか、変わらなかったので、ある時、ない時で、どこがどう変わるのか、わかる範囲で調べた。
1.管理画面の表示
models.pyに__str__がついていない時
Customer object(1)と表示されている。何が登録してあるのかぱっと見わからない。
models.pyに__str__がついている時
フォームから「かかし」と2回登録したので、「かかし」と表示されている。
strがついていない時よりも、ついていた方が、データが見やすい。
表示されるデータ名は、
・ついていない時は、テーブル名+object(番号)
・ついているときは、登録したテキスト
という違いがあった。
つまり、あそこに指定した内容によって管理画面の表示が変わる。ということか?
def __str__(self):
return self.name
def __str__(self):
return "/" + self.name + "/"
以下のように表示された。「かかし」の前後にスラッシュが入っている。
2.htmlの書き方
models.pyに__str__がついていない時のHTML画面
表記を以下のようにした。
<ul>{{customer}}</ul>
strを付けておかないと、管理画面同様、Customer objenct(1)と出てしまう。
{% extends 'base.html' %} {% block body-contents %} <a href="customercreate">新規追加</a> {% for customer in object_list %} <ul>{{customer}}</ul> {% endfor %} {% endblock %}
次に、models.pyのstrはつけないまま、HTMLの書き方を変えてみた。
<ul>{{customer.name}}</ul>
かかしと表示されている。
{% extends 'base.html' %} {% block body-contents %} <a href="customercreate">新規追加</a> {% for customer in object_list %} <ul>{{customer.name}}</ul> {% endfor %} {% endblock %}
models.pyに__str__がついている時のHTML画面
同じように両方試してみたら、両方とも同じ表示で、かかしと表示された。
<ul>{{customer}}</ul>
<ul>{{customer.name}}</ul>
ここまで書いて、結局どうなのか?と言われると、ケースバイケースだと思うので、よくわからない。しかし、def __str__ ・・・のくだりは、書いてあると何かとわかりやすいので、使いやすいように書いたらいいのかな?と思った。
2.データベースに反映させる(マイグレーション)
models.pyで設定した内容をデータベースに反映させるために、マイグレーション(移動する的な意味)の手順を実行する。
まずは、コマンドプロンプトを立ち上げる。
そうしたら、djangoのプロジェクトフォルダへ移動する。
例)cd desktop\project_name
プロジェクトフォルダに移動したら以下を実行する
python manage.py makemigrations app_name
実行したらmodels.pyの情報を元に、マイグレーションファイルを自動的に作成してくれる。
次に、以下を実行する
python manage.py migrate
上記のような画面が出てきたら、成功!
1回目、エラーが出たので解説。
3.頭を一度整理する
これで、データベースを使えるようになったので、フォームを作ったらデータベースに登録できるようになった。あとは、登録したものがみれたらOK。
つまり、大きくわけると、【登録フォーム画面】と【データ一覧画面】があればOK
登録フォーム画面に必要なものリスト
・登録用のURL(urls.py)
・フォーム内容(forms.py)
・フォーム内容の表示設定(views.py)
・フォーム内容の表示(〇〇.html)
・入力項目+登録ボタン(<form></form>)
データ一覧画面に必要なものリスト
・一覧表示用のURL(urls.py)
・一覧画面の表示設定(views.py)
・一覧画面の表示(〇〇.html)
・データベースの内容を表示({{〇〇〇}})
次やること
・登録フォーム画面のURLをcustomercreateにする。
・データ一覧画面のURLをcustomerにする。
4.urls.pyにurlを追加する
場所
project_name > app_name > urls.py
from django.urls import path from . import views urlpatterns = [ path('index',views.IndexView.as_view(),name="index"), path('staff',views.staff,name='staff'), # path('customer',views.customer,name='customer'), path('customer',views.CustomerView.as_view(),name='customer'), path('customercreate',views.CustomerCreateView.as_view(),name='customercreate'), path('project',views.project,name='project'), path('pay',views.pay,name='pay'), # path('contact',views.contact,name='contact'), ]
8行目
path('customer',views.CustomerView.as_view(),name='customer')
customer(一覧表示画面)にアクセスしたら、viws.pyのCustomerViewの処理をする。という意味。
9行目path('customercreate',views.CustomerCreateView.as_view(),name='customercreate')
customercreate(フォーム画面)にアクセスしたら、viws.pyのCustomerCreateViewの処理をする。という意味。
この時点では両方ともviews.pyには何も書いていない。
5.forms.pyにフォーム内容を記載する
場所
project_name > app_name > forms.py
from django import forms from . models import Customer class CustomerForm(forms.ModelForm): class Meta: models = Customer fields = ('name',)
importで、Customerモデルをインポートして、CustomerFormクラスを作って、models=のところへ、Customerをセットする。fieldsはmodels.pyで設定したカラム名を入れる。そしたら、入力フォームとして利用できるようになる。
以下の太字の部分のこと。(models.pyを抜粋)
from django.db import models
# Create your models here.
class Customer(models.Model):
name = models.CharField(max_length=255)
def __str__(self):
return self.name
6.views.pyに表示関係を記載する
場所
project_name > app_name > views.py
from django.shortcuts import render from django.http import HttpResponse from django.shortcuts import redirect from django.views import generic from .models import Customer # from .forms import ContactForm class CustomerView(generic.ListView): model = Customer template_name = 'customer.html' class CustomerCreateView(generic.CreateView): model = Customer fields = ('name',) template_name = 'customercreate.html' success_url = 'customer'
※上記は必要な部分だけを抜粋している。
一覧を表示させるためのListViewとCreateの時に使う、CreateViewを使っている。
CustomerCreateViewのところに、success_urlというのがある。
これは、フォームに情報を入力して登録したあと、どこのページに遷移するのか?を設定している。
success_url を記載せずに、フォームに入力した場合どうなるか?
エラーが表示される。
No URL to redirect to. Either provide a url or define a get_absolute_url method on the Model.
エラー内容のGoogle翻訳
リダイレクト先のURLがありません。 URLを指定するか、モデルでget_absolute_urlメソッドを定義してください。
models.pyにget_absolute_urlを設定しなければいけない。とうこと。
本来ならmodel.pyへこれを記載するが、その前に、エラーがでたけど、データベースに登録できているかどうかを見てみる。
エラーは出ているけど、データベースには登録されている。
success_url にURLを記載した場合
success_url = 'customer.html'と記載した場合
以下のように、ページがありません。となる。
success_url = 'customer'と記載した場合、kakasiと入力して登録を押してみる。
customerページに飛んで、一番下にkakasiと表示されている!エラーも出ていない!
つまり、success_url = には、urls.pyに指定しているURL先を記載したらいいということか!
でも、models.pyにget_absolute_urlを設定しなければいけない。というのは、どうしたものか。違う方法でエラーが消えた。本当は書かないといけないと思うが、今はまだよく調べていないので、宿題にする。
7.htmlファイルを編集する
場所
project_name > app_name > templates> customer.html
customercreate.html
まずはcustomer.htmlから。
これは、一覧を表示するファイル。
{% extends 'base.html' %} {% block body-contents %} <a href="customercreate">新規追加</a> {% for customer in object_list %} <ul>{{customer}}</ul> {% endfor %} {% endblock %}
base.htmlは前の記事でまとめた通り。
3行目で、customercreateにリンクしているので、フォーム画面へ飛ぶ。
{% for customer in object_list %}
のcustomerは変数だから、for i in range()とかで使っているように、「i」でも別に構わない。
object_list は、初めからデフォルトとして決まっている。自分では設定していない。
object_list以外の名前にカスタマイズすることも可能。この辺りはListViewの機能としてそろっている。context_object_name=リスト名 で変更可能。
一般的な表示ビュー Djangoドキュメント
https://docs.djangoproject.com/en/3.0/ref/class-based-views/generic-display/
次に、customercreate.html
これは、フォームを表示させて、データベースに登録する画面
{% extends 'base.html' %} {% block body-contents %} <form method='POST'> {% csrf_token %} {{form.as_p}} <button type="submit">登録</button> </form> {% endblock %}
こんな感じで表示される。フォームのデザイン自体触っていないし、一行なので、めっちゃシンプル。見やすくしたり、するのは次の記事にしようと思う。
フォームの操作 Djangoドキュメント
https://docs.djangoproject.com/en/3.0/topics/forms/
管理画面の発行
1.コマンドを開いて、プロジェクトフォルダまで移動する
2.python manage.py createsuperuser
3.ユーザー名入力
4.メールアドレス(入力せずエンターでもOK)
5.Password:8文字以上で入力する。
※8文字以下でもいけるし、パスワードは入力してもコマンド上に表示されない。
入力してエンターを押したら、Password(again)が表示されるので同じパスワードを入力する。
次はそのままサーバーを立ち上げる。
6.python manage.py runserver
7.http://127.0.0.1:8000/admin/ に接続する。
models.pyの設定を行っていれば、ここのテーブル名も表示されるが、今は表示されていない。表示させるためには、admin.pyに記載を記述する必要がある。
8.admin.pyを下記のように一行追加する。※(Customer)はテーブル名
from django.contrib import admin from .models import Customer # Register your models here. admin.site.register(Customer)
9.http://127.0.0.1:8000/admin/へアクセスするとCustomerが表示されている。
この画面からもデータの追加、削除が行える。
総括
モデルとフォームをどうしていいものかずっとわからなかったので、今回まとめられてよかった。まだまだやっていくうちにわからないところが出てくると思うが、一旦機能として使えることは使えるようになったので、自分でカスタマイズして作ってみる。
次は、カラムを増やして、登録フォームと表示フォームも綺麗に整えて、もうちょっと顧客管理システムっぽくしてもみようと思う。