Django学習

【Python】初めてのDjangoフォームの使い方【クラスベース】

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というカラム名がありますよ。という意味。

一番下に書いてある、これは何か?

def __str__(self):
    return self.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の書き方

解説ではまだ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 を記載せずに、フォームに入力した場合どうなるか?

解説ではまだhtmlファイルをは作っていないので、本来この段階ではフォームへ入力することは出来ない。

エラーが表示される。
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が表示されている。
この画面からもデータの追加、削除が行える。

 

総括

モデルとフォームをどうしていいものかずっとわからなかったので、今回まとめられてよかった。まだまだやっていくうちにわからないところが出てくると思うが、一旦機能として使えることは使えるようになったので、自分でカスタマイズして作ってみる。

次は、カラムを増やして、登録フォームと表示フォームも綺麗に整えて、もうちょっと顧客管理システムっぽくしてもみようと思う。