皆さん、こんにちは。今日はDjangoのFormクラスについて紹介したいと思います。 前回までで説明した事は以下になります。
フォルダの構造は以下の様になっています。
mysite
├── hello
│ ├── admin.py
│ ├── apps.py
│ ├── fixtures
│ │ └── test-data.json
│ ├── __init__.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ ├── __init__.py
│ │ └── __pycache__
│ │ ├── 0001_initial.cpython-36.pyc
│ │ └── __init__.cpython-36.pyc
│ ├── models.py
│ ├── __pycache__
│ │ ├── admin.cpython-36.pyc
│ │ ├── __init__.cpython-36.pyc
│ │ ├── models.cpython-36.pyc
│ │ ├── urls.cpython-36.pyc
│ │ └── views.cpython-36.pyc
│ ├── static
│ │ └── css
│ │ ├── bootstrap.min.css
│ │ └── style.css
│ ├── templates
│ │ └── index.html
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── manage.py
└── mysite
├── asgi.py
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-36.pyc
│ ├── settings.cpython-36.pyc
│ ├── urls.cpython-36.pyc
│ └── wsgi.cpython-36.pyc
├── settings.py
├── urls.py
└── wsgi.py
Formの説明
DjangoにはFormクラスの機能があります。
この機能を使うとhtml内でpythonで作られたフォームを表示する事ができます。
その上、バリデーション機能や他の機能を簡単に実装できるので、
formなどを作る時動く便利です。
今回はFormの引数や表示方法について紹介します。
Formのコアフィールド引数
フォームはこれらの引数をつけられます。 引数はいかになります。
フィールド引数 | 説明 |
---|---|
required | 項目が必要か必要でないかを設定します。TrueかFalseをつけられます。デフォルトではTrueです。なので空白やclean()した場合ValidationErrorがおきます。 |
label | 項目にラベルをつけます。ラベルは文字列です。デフォルトの場合アンダースコアを空白、最初の文字を大文字に変換して生成されます。 |
label_suffix | ラベルの後の記号です。デフォルトではコロンです。これを設定する事で記号をオーバーライドできます。 |
initial | 初期値を設定します。 |
widget | widgetをしていします。Widgetの種類はオフィシャルページを見てください。 |
help_text | Fieldを説明するテキストです。テンプレートに渡した後、テンプレート内でフォームのフィールド.help_textやフォーム.as_pなどで表示できます。 |
error_messages | 辞書型で渡すことで、ValidationErrorが起きた時渡した値となります。 |
validators | バリデーション関数の設定。関数の一覧はオフィシャルページを見てください。カスタム(自分で設定)する事もできます。 |
localize | formデータの入力とレンダリングした出力のローカライゼーションを有効にします。 |
disabled | TrueかFalseをつけられます。Trueの場合フォームの値を編集することはできません。 |
FormのFieldクラス
DjangoのFieldクラスは以下になります。
フィールドクラス | 既定のウィジェット | 説明 | エラーメッセージキー |
---|---|---|---|
BooleanField | CheckboxInput | チェックすることができる。同時にrequired = Trueの時チェックしているかチェックする。 | required |
CharField | TextInput | 文字列を入力する事ができる。同時にmax_length、min_lengthがある場合そのバリデーション関数が存在しチェックする。 | required,max_length,min_length |
ChoiceField | Select | リストから選択する。同時に値がリストに存在するかチェックする。 | required,invalid_choice |
TypedChoiceField | Select | リストから選択する。同時に値がリストに存在するかチェックする。選択した値の型はcoerceで指定した型になる | required,invalid_choice |
DateField | DateInput | 日付のフォーマットを入力することができる。同時にdatetime.date、datetime.datetime又は指定した文字列型のフォーマットかをチェックする。(input_formatsオプションで指定する事ができる) | required,invalid |
DateTimeField | DateTimeInput | 日付のフォーマットを入力することができる。同時にdatetime.date、datetime.datetime又は指定した文字列型のフォーマットかをチェックする。(input_formatsオプションで指定する事ができる) | required,invalid |
DecimalField | Field.localize=True -->NumberInput それ以外TextInput | 小数を入力することができる。同時に値がDecimalかチェックする。max_value、min_valueがある場合そのバリデーション関数が存在しチェックする。 | required,invalid,max_value, min_value,max_digits, max_decimal_places, max_whole_digits |
DurationField | TextInput | 文字列を入力する。同時にTimedelta型に変換できる文字列かチェックする。値はdatetime.timedelta.minとdatetime.timedelta.maxの合間かをチェックする。 | required,invalid,overflow |
EmailField | EmailInput | メールアドレスを入力する。同時にメールアドレスかチェックする。max_length、min_lengthがある場合そのバリデーション関数が存在しチェックする。 | required,invalid |
FileField | ClearableFileInput | ファイルをアップロードする。同時にファイルをアップロードしたかチェックする。 | required,invalid,missing,empty, max_length |
FilePathField | Select | ディレクトリを指定しその中のファイル/フォルダを選択できるようにする。 | required,invalid |
FloatField | Field.localize=True -->NumberInput それ以外TextInput | Float型を入力する。同時にmax_value、min_valueがある場合そのバリデーション関数が存在しチェックする。 | required, invalid, max_value, min_value |
ImageField | ClearableFileInput | ファイルをアップロードする。同時にファイルをアップロードしたかチェックし、ファイルの種類がPillowにサポートされてるかチェックする。 | required, invalid, empty, missing, invalid_image |
IntegerField | Field.localize=True -->NumberInput それ以外TextInput | 整数を入力することができる。同時にmax_value、min_valueがある場合そのバリデーション関数が存在しチェックする。 | required, invalid, max_value, min_value |
GenericIPAddressField | TextInput | IPv4、IPv6を入力する。同時にIPアドレスが有効なIPアドレスかをチェックする。 | required,invalid |
MultipleChoiceField | SelectMultiple | リストから選択する(上限が一つではない)。同時に値がリストに存在するかチェックする。 | required, invalid_choice, invalid_list |
TypedMultipleChoiceField | SelectMultiple | リストから選択する(上限が一つではない)。同時に値がリストに存在するかチェックする。選択した値の型はcoerceで指定した型になる | required,invalid_choice |
NullBooleanField | NullBooleanSelect | 値がTrue,False,Noneになる。 | 無 |
RegexField | TextInput | 正規表現の文字列を入力する。同時にRegexValidatorで正規表現をチェックする。 | required,invalid |
SlugField | TextInput | 文字、数字、アンダースコア、ハイフンのみを含むことをチェックする。 | required,invalid |
TimeField | TimeInput | 時間のフォーマットを入力することができる。同時にdatetime.time又は指定した文字列型のフォーマットかをチェックする。(input_formatsオプションで指定する事ができる) | required,invalid |
URLField | URLInput | URLを入力する。同時にURLが有効化チェックする。 | required,invalid |
UUIDField | TextInput | 文字列を入力することができる。(hex(16進数)として受け取ることができる文字列) | required,invalid |
Formを表示するための準備
今回Formを表示するテンプレートを新たに作ります。
そして本来の見栄えも変えます。
新しく作るhtmlの名前はcreate.htmlです。
フォームは.as_tableを使ってテーブルの様に表示します。
ではmysite/templates/の中にcreate.htmlをつくります。
そして以下の様に編集します。
{% load static %}
<html>
<head>
<meta charset=UTF-8>
<title>Form test</title>
<link rel=stylesheet href={% static 'css/style.css' %}>
</head>
<body>
<h1>Please enter forms below</h1>
<form action = {% url 'index' %} method=POST class='form'>
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<button type=submit>Submit</button>
</form>
</body>
<html>
index.htmlはデータが渡された時そのデータを表示します。
mysite/templates/index.htmlを以下の様に編集します。
{% load static %}
<html>
<head>
<meta charset=UTF-8>
<title>Original Page</title>
<link rel=stylesheet href={% static 'css/bootstrap.min.css' %}>
<link rel=stylesheet href={% static 'css/style.css' %}>
</head>
<body>
<h1>Welcome to the tutorial</h1>
<div class=go-form>
<a href = {% url 'forms' %} class = go-form-button>Fill form</a>
</div>
{% if data %}
<table class=table>
<thead>
<tr>
<th scope=col>#</th>
<th scope=col>Last</th>
<th scope=col>First</th>
<th scope=col>Gender</th>
<th scope=col>Age</th>
<th scope=col>Occupation</th>
<th scope=col>Birthday</th>
<th scope=col>Email</th>
</tr>
</thead>
<tbody>
<tr>
<th scope=row>1</th>
{% for key,value in data.items %}
<td>{{value}}</td>
{% endfor %}
</tr>
</tbody>
</table>
{% endif %}
</body>
<html>
補足:{% csrf_token %}はCSRF攻撃を防ぐものです。(簡単にいうとフォームのリクエストをチェックするという意味です。)
そしてmysite/hello/static/css/のstyle.cssも編集します。
以下の様に編集します。
@charset UTF-8;
body{
margin:0;
text-align:center;
}
.go-form-button{
color:black;
}
.form table{
margin:0 auto;
}
Formの表示方法 Formの表示方法は以下になります。
- アプリフォルダの中にforms.pyを作り、その中に項目を記述します。
- そのフォームをviews.pyで表示したいテンプレートに渡します。
では実際にフォームを作ってみましょう。
まずmysite/hello/の中にforms.pyを作ります。
そしてformの項目はいかになります。
- 姓
- 名
- 性別
- 年齢
- 職業
- 誕生日
- メールアドレス
(後にモデルから継承する時に二つのフォームが違うことが、 分かるように職業をいれています。)
そしてforms.pyを以下の様に編集します。
from django import forms
class SampleForm(forms.Form):
sex = [
('Male','Male'),
('Female','Female'),
]
last_name = forms.CharField(label='Last Name')
first_name = forms.CharField(label='First Name')
gender = forms.ChoiceField(label='Gender', choices = sex)
age = forms.IntegerField(label='Age')
occupation = forms.CharField(label = 'Occupation')
birthday = forms.DateField(label='Birthday')
email = forms.EmailField(label='Email')
そしてindex.htmlでフォームのデータを受け取れる様、 views.pyを以下の様に編集します。
from django.shortcuts import render
from .forms import SampleForm
def show_index(request):
# リクエストがPOSTだったら内容を表示する
if request.method == 'POST':
params = {
Last:request.POST.get('last_name'),
first:request.POST.get('first_name'),
gender:request.POST.get('gender'),
age:request.POST.get('age'),
occupation:request.POST.get('occupation'),
birthday:request.POST.get('birthday'),
email:request.POST.get('email')
}
return render(request, 'index.html', {'data':params})
# POSTじゃなかったら表示する
return render(request,'index.html')
def show_forms(request):
return render(request, 'forms.html',{'form':SampleForm()})
ではurls.pyを以下の様に編集してください。
from django.urls import path
from . import views
urlpatterns = [
path('',views.show_index, name='index'),
path('forms',views.show_forms,name='forms')
]
これで準備は整いました。 コマンドをうって確かめてみましょう。
python manage.py runserver 0:8000
そして<ipアドレス>:8000/helloに行くと以下の様になってます。

そしてFill Formをクリックします。するといかになります。

このフォームを完成します。

そしてindex.html画面に戻り以下の様になります。

Formをモデルから継承
方法は以下になります。
- modelをインポートします。
- ModelFormを使って継承させます。
では実際にやってみます。
mysite/helllo/forms.pyを以下の様に編集します。
from django import forms
from .models import Personinfo
class SampleForm(forms.ModelForm):
class Meta:
model = Personinfo
fields = ['last_name','first_name','gender','age','birthday','email']
そしてmysite/helllo/views.pyのOccupationを削除します。
コードは以下になります。
from django.shortcuts import render
from .forms import SampleForm
def show_index(request):
# リクエストがPOSTだったら内容を表示する
if request.method == 'POST':
params = {
Last:request.POST.get('last_name'),
first:request.POST.get('first_name'),
gender:request.POST.get('gender'),
age:request.POST.get('age'),
birthday:request.POST.get('birthday'),
email:request.POST.get('email')
}
return render(request, 'index.html', {'data':params})
# POSTじゃなかったら表示する
return render(request,'index.html')
def show_forms(request):
return render(request, 'forms.html',{'form':SampleForm()})
最後にindex.htmlのOccupationを削除して完成です。
{% load static %}
<html>
<head>
<meta charset=UTF-8>
<title>Original Page</title>
<link rel=stylesheet href={% static 'css/bootstrap.min.css' %}>
<link rel=stylesheet href={% static 'css/style.css' %}>
</head>
<body>
<h1>Welcome to the tutorial</h1>
<div class=go-form>
<a href = {% url 'forms' %} class = go-form-button>Fill form</a>
</div>
{% if data %}
<table class=table>
<thead>
<tr>
<th scope=col>#</th>
<th scope=col>Last</th>
<th scope=col>First</th>
<th scope=col>Gender</th>
<th scope=col>Age</th>
<th scope=col>Birthday</th>
<th scope=col>Email</th>
</tr>
</thead>
<tbody>
<tr>
<th scope=row>1</th>
{% for key,value in data.items %}
<td>{{value}}</td>
{% endfor %}
</tr>
</tbody>
</table>
{% endif %}
</body>
<html>
これで準備完了です。 コマンドをうって確かめてみましょう。
python manage.py runserver 0:8000
そして<ipアドレス>:8000/helloに行くと以下の様になってます。

そしてFill Formをクリックします。するといかになります。

このフォームを完成します。

そしてindex.html画面に戻り以下の様になります。

次回はこのフォームを使ってデータベースに入れる方法を、紹介します。