このページでは、models.Field
のサブクラスのコンストラクタ、すなわちモデルクラスのフィールドに指定可能な null
引数と blank
引数について説明していきたいと思います。
Django では、models.py
でのモデルクラスの定義によってデータベースのテーブルの形式を定義することができます。具体的には、モデルクラスに定義したフィールドと同等のフィールド(カラム)を持つテーブルを定義することができます。
そして、このモデルクラスのフィールドは、モデルクラスに models.Field
のサブクラスのインスタンスを参照するクラス変数を定義することで実現できます。そして、models.Field
のサブクラスのインスタンスを生成するのに、models.Field
のサブクラスのコンストラクタを実行することになります。そして、このコンストラクタには null
引数と blank
引数が指定可能です。
他の言語で NULL について学んだことのある方であれば、もしかしたらこれらの引数に同じようなイメージを持つ方もおられるかもしれませんが、これらは明確に異なる引数になります。このページでは、これらの null
引数と blank
引数の違い・意味合いについて説明していきます。
また、上記に登場した「モデルクラス」に関しては、別途下記ページで詳細を解説していますので、モデルクラスについて復習したい方は是非下記ページを読んでみてください。
【Django入門6】モデルの基本Contents
null
引数と blank
引数の違い
それでは、 null
引数と blank
引数の違いについて説明していきたいと思います。
以降では、models.Field
のサブクラスのコンストラクタのことを単に「フィールド」と記して説明していきます。
まず、これらは、フィールドに指定可能な引数であるという点は共通です。その一方で、データベースのテーブルに作用するか、フォームに作用するかという点が異なります。
null
引数は「テーブル」の設定を行う引数
null
引数は、テーブルのフィールドに関する設定を行う引数となります。
前述の通り、モデルクラスはテーブルに対応しており、テーブルはモデルクラスに定義したフィールドと同等のフィールド(カラム)を持つことになります。そして、フィールドへの null
引数の指定により、そのフィールドが空の状態のレコードのテーブルへの保存の可否を設定することが可能となっています。null
引数のデフォルトは False
となります。
null=True
が指定されている場合は、そのフィールドが空の状態のレコードのテーブルへの保存が可能となります。
それに対し、null=False
が指定されている場合は、そのフィールドが空の状態のレコードのテーブルへの保存が不可となります。
具体的には、null=False
が指定されているフィールドが空の状態のレコードをテーブルに保存しようとすると、下記のような例外が発生して保存に失敗することになります。したがって、下記のような例外が発生した場合は、そのフィールドが空であるレコードを保存しようとしていることが問題であるため、そのフィールドを空でないようにしてからレコードを保存してやれば例外が解消されることになります。
django.db.utils.IntegrityError: NOT NULL constraint failed: テーブル名.フィールド名
スポンサーリンク
blank
引数は「フォーム」の設定を行う引数
それに対し、blank
引数は、フォームのフィールドに関する設定を行う引数となります。
Django には、モデルフォームという、モデルクラスからフォームを定義する仕組みが存在します。このモデルフォームでは、ベースとして指定したモデルクラスに定義されたフィールドと同等のフィールドを持つフォームを定義することが可能です(フォームに持たせるフィールドは選択可能です)。
そして、この blank
引数は、そのベースとなるモデルクラスのフィールドに対応するフォームのフィールドの設定を行う引数となります。具体的には、そのフォームのフィールドが空である場合の妥当性の検証結果を設定する引数となります。blank
引数のデフォルトに関してもは False
となります。
blank=True
が指定されている場合は、そのフィールドが空の場合に、妥当性の検証で「妥当である」と判断されるようになります。それに対し、blank=False
が指定されている場合は、そのフィールドが空の場合に、妥当性の検証で「妥当でない」と判断されるようになります。
妥当性の検証
また、この妥当性の検証は、フォームの各種フィールドの設定に基づき、ウェブブラウザに表示されたフォームからのデータの送信時にも実施されることになりますし、ウェブアプリがデータを受信したときにも実施されることになります。
フォームやフォームクラス、さらには妥当性の検証に関しては下記ページで解説していますので、これらについて詳しく知りたい方は下記ページを参照していただければと思います。
【Django入門5】フォームの基本データ送信時の妥当性の検証
分かりやすいのがフォームからのデータ送信時に実施される妥当性の検証になると思います。フォームからのデータの送信時には、フォームの各種フィールドに入力された値に対して妥当性の検証が行われるようになっています。そして、1つでも入力された値が「妥当でない」と判断された場合、フォームからのデータの送信が行えなくなります。
したがって、blank=True
が指定されているフィールドに関しては、そのフィールドが空であっても「妥当である」と判断されることになるため、そのフィールドが空であることが原因でフォームからのデータの送信が不可となることはありません。他のフィールドが全て妥当であれば、そのフィールドが空の状態でもフォームからのデータの送信は実行可能となります。
それに対し、blank=False
が指定されているフィールドに関しては、そのフィールドが空であれば「妥当でない」と判断されることになるため、そのフィールドが空であればフォームからのデータの送信が不可となります。
ちなみに、ウェブブラウザに表示されるフォームの各種フィールドに対して妥当性の検証が行われるのは、フォームクラスのフィールドの引数にしたがって各種フィールドのタグが生成されるからになります。blank=False
が指定されているフィールドに対応するタグには required
属性が指定されることになるため、空の状態だと妥当でないと判断されることになります。
データ受信時の妥当性の検証
また、前述の通り、Django で開発するウェブアプリにおいては(おそらく他のフレームワーク等で開発するウェブアプリにおいても)、データを受信したときに、受信したデータの妥当性の検証を行うのが一般的です。この妥当性の検証は、受信したデータを引数に指定してフォームクラスのインスタンスを生成し、さらに、そのインスタンスに is_valid
メソッドを実行させることで実施することが可能です。
で、このように生成したインスタンスに is_valid
メソッドを実行させれば、各種フィールドに対して妥当性の検証が実行されることになり、この時に、空のフィールドを「妥当である」or「妥当でない」のどちらと判断するかが、そのフィールドの blank
引数によって決まることになります。is_valid
メソッドはフォームクラスのインスタンスから実行されるため、この妥当性の検証に関しても、フォームの設定を行う blank
引数に従って結果が変化することになります。
具体的には、blank=True
が指定されているフィールドが空であれば、そのフィールドの値は「妥当である」と判断されることになります。
それに対し、blank=False
が指定されているフィールドが空であれば、そのフィールドの値は「妥当でない」と判断されることになります。
この、”フィールドが空” とは、具体的には、そのフィールド自体が存在しない or フィールドの値が空文字列(''
)であることを指しています。
2つの妥当性の検証の必要性
ここまで説明してきた通り、blank
引数は、データ送信時、及び、データ受信時に実施される妥当性の検証に作用する引数となります。
もしかしたら、ここまでの説明を読んで、妥当性の検証はデータ送信時のみ行えば良いと考えた人もおられるかもしれません。ですが、データ送信時の妥当性の検証は実施されない可能性があるので、データ受信時の妥当性の検証も必要となります。
例えば、ウェブアプリから受信したフォームでデータを送信する場合は、基本的にはデータ送信時の妥当性の検証が実施されることになります。ですが、フォームを介さず、直接 Python スクリプト等からデータをウェブアプリに送信することも可能で、その場合はデータ送信時の妥当性の検証が行われません。
また、悪意あるユーザーから悪意あるデータが送信されてくる可能性もありますので、データ受信時の妥当性の検証もウェブアプリには必要となります。そして、安全にデータを扱うため、妥当性の検証で「妥当である」と判断された場合のみ、受信したデータを扱った処理(データのレコードとしての保存など)を実施するようにウェブアプリを開発する必要あります。
blank
引数はモデルクラスフォームに対して有効
また、この blank
引数はモデルクラスのフィールドに指定するものであるため、モデルクラスをベースとしてフォームを作成するモデルフォームクラスを定義しない場合は、blank
引数の指定は無意味であることに注意してください。
モデルフォームクラスではなく、単なるフォームクラスを定義し、そのクラスにフィールドを定義するようなことも可能です。この場合には、blank
引数ではなく required
引数によって、フィールドが空の場合の妥当性の検証の結果を設定することになります。required
引数の場合は False
指定した場合に空のフィールドを「妥当である」と判断し、True
を指定した場合に「妥当でない」と判断することになり、blank
引数とはTrue
/ False
の意味合いが逆になるので注意してください。
null
引数 x blank
引数の組み合わせとウェブアプリの動作
null
引数と blank
引数の意味合いについては理解していただけたでしょうか?
null
引数と blank
引数には、それぞれ True
/ False
を指定することが可能です(引数を指定しなかった場合は、両方ともデフォルトの False
指定となる)。つまり、各フィールドに対し、null
引数と blank
引数の指定の仕方の組み合わせは4パターン存在することになります。
ここからは、今まで解説してきた内容のおさらいの意味も含め、これらの4つの組み合わせで null
引数と blank
引数を指定した場合のウェブアプリの動作や注意点等について解説していきます。
null=False
/ blank=False
(デフォルト)
まずは、null=False
と blank=False
を指定するパターンが挙げられます。この組み合わせのパターンはデフォルト設定となります。
考え方も単純で、この場合は、そのフィールドが空であれば妥当でないと判断され、さらに、そのフィールドが空の状態のレコードはテーブルへの保存も不可となります。
基本的に、この組み合わせが一番安全なパターンとなります。なので、null
引数と blank
引数の指定の仕方に迷うのであれば、この組み合わせの引数指定を行うのが一番無難だと思います。
スポンサーリンク
null=True
/ blank=True
2つ目は null=True
と blank=True
を指定するパターンになります。
これも考え方も単純で、この場合は、そのフィールドが空の状態でもフォームからの送信が可となります。また、そのフィールドが空のデータをウェブアプリが受信したとしても「妥当である」と判断されることになります。さらに、そのフィールドが空の状態のレコードもテーブルに保存可となります。
つまり、そのフィールドに値を入力するかどうかはユーザーが決めることができます。そして、フィールドが空であったとしても、そのフォームから受信したデータに基づいて生成したレコードをテーブルに保存することが可能となります。
ただし、これは null=True
や blank=True
を指定する他のパターンでも共通して言えることになるのですが、これらを指定したフィールドの場合、妥当性の検証で「妥当である」と判断されたデータであったとしても、データベースから取得したレコードであったとしても、そのフィールドが空(None
)である可能性があるという点に注意が必要となります。
そのため、null=True
や blank=True
を指定するフィールドの値を扱う処理は、その値が None
であることを考慮して実装する必要があります。
blank=False
が指定されているフィールドの値は、妥当性の検証で「妥当である」と判断された場合は必ず None
以外の値となるため、妥当性の検証で「妥当である」と判断された後の処理は None
であることを考慮せずに実装することができます。また、null=True
が指定されているフィールドは空の状態ではテーブルに保存できないため、テーブルから取得したレコードのそのフィールドは必ず None
以外の値となります。なので、テーブルから取得したレコードに関しては、そのフィールドが None
であることを考慮せずに扱うことができます。
ですが、null=True
や blank=True
を指定したフィールドは、上記のような場合にも、そのフィールドの値が None
であることがあるため、まず、そのフィールドが None
であるかどうかで条件分岐を行い、None
の場合は処理をスキップしたり、デフォルトの値を用いて処理を実施したりする必要があります。
例えば、下記は引数で指定された pk
をプライマリーキーとする User
のレコードの age
フィールドを用いて、その User
のレコードが未成年のものであるかどうかを判断する関数となります。age
フィールドが IntegerField
であり、さらに null=False
を指定している場合は age
フィールドは None
となることが無いため、下記の処理は正常に動作することになります。
def is_minor(pk):
user = User.objects.get(pk=pk)
if user.age < 18:
return True
else:
return False
ですが、age
フィールドに null=True
が指定されている場合、age
フィールドが空の状態でもレコードとしてテーブルに保存可能です。つまり、テーブルから取得したレコードの age
フィールドは空、値としては None
である可能性があるということになります。
もし、取得したレコードの age
フィールドの値が None
であれば、上記の user.age < 18
の箇所で例外が発生することになります。なので、age
フィールドに null=True
が指定されているのであれば、age
フィールドが None
である可能性を考慮し、その時に例外が発生しないような処理を実装する必要があります。例えば、次のように age
フィールドが None
の場合に比較を実施せずに True
を返却するようにすれば、とりあえず例外は防げることになります。
def is_minor(pk):
user = User.objects.get(pk=pk)
if user.age is None:
return True
if user.age < 18:
return True
else:
return False
こここまで説明してきたように、null=True
や blank=True
を指定することで、ユーザーが不要な入力をスキップできるようになるというメリットが得られる一方で、ウェブアプリ内部の処理が複雑になるというデメリットがあります。もちろん、メリットも大きいので、これらを指定すること自体が NG というわけではないですが、null=True
や blank=True
を指定する場合は、そのフィールドの値が None
となる可能性を考慮して実装する必要があることは覚えておいてください。
null=False
/ blank=True
3つ目は null=False
と blank=True
を指定するパターンになります。
この場合は、そのフィールドが空の状態でもフォームからの送信が可となります。また、そのフィールドが空のデータをウェブアプリが受信したとしても妥当であると判断されることになります。ですが、そのフィールドが空の状態のレコードはテーブルに保存不可となります。
つまり、そのフィールドが空の状態のデータを受信したとしても妥当性の検証では「妥当である」と判断されることになりますが、その受信したデータをそのままレコードとしてテーブルに保存しようとすると基本的には例外が発生することになります。
blank=True
を指定することで、ユーザーが不要なフィールドへの入力をスキップできるようになるというメリットは得られるのですが、結局 null=False
の効果で、そのデータのレコードとしてのテーブルへの保存時に例外が発生するのであれば意味が無いようにも思えますね。
ただ、このテーブルへの保存時の例外を防ぐことができるのであれば、この組み合わせのパターンにも使い道があることになります。
例えば、下記の2つのケースにおいては、そのフィールドが空であってもレコードの保存に成功することになります。
- そのフィールドが文字列を扱うフィールドである(
CharField
やTextField
) - そのフィールドに
default
引数が指定されている
前者の場合、空のフィールドは空文字列(''
)として保存されることになるため、null=False
が指定されていても例外が発生しません。後者の場合、空のフィールドは default
引数に指定された値として保存されることになるため、null=False
が指定されていても例外が発生しません。また、上記の2つに当てはまらなくても、空のフィールドが送信されてきたときに、そのフィールドに何らかの妥当な値をセットしてからレコードとして保存するようにすれば、空のフィールドが送信されてきたとしても例外の発生を防ぐことが可能です。
このように、空のフィールドが送信されてきたとしても、保存時に自動的に空のフィールドに値がセットされる仕組みを利用したり、空のフィールドに値をセットしてからレコードを保存するような処理を実装したりする場合は、null=False
と blank=True
の組み合わせが有効になります。ただし、これらが行われない場合、前述の通り、送信されてきたデータをそのままレコードとして保存すると例外が発生することになるので、この点には注意が必要となります。
null=True
/ blank=False
最後の4つ目は null=True
と blank=False
を指定するパターンになります。
この場合、そのフィールドが空の状態でのフォームからの送信は不可となり、また、そのフィールドが空のデータをウェブアプリが受信したと場合にも妥当でないと判断されることになります。ですが、そのフィールドが空の状態のレコードもテーブルに保存可となります。
基本的に、ウェブアプリでは送信されてきたデータに対して妥当性の検証を実施し、妥当であると判断された場合のみ、送信されてきたデータをレコードとしてテーブルに保存するようにすることが多いです。したがって、この組み合わせで引数を指定したフィールドは、レコードとしてテーブルに保存するタイミングでは空でないことが保証されていることになります。
つまり、null=True
を指定したフィールドが空の状態のレコードが保存されることが基本的にはあり得ないため、null=True
を指定しても意味が無いことになります。
そのため、null=True
と blank=False
の組み合わせで引数を指定する意味はなく、この組み合わせを指定するのであれば、null=False
と blank=False
の組み合わせを指定した方が良いと思います。
スポンサーリンク
まとめ
このページでは、モデルクラスのフィールドに指定する null
引数と blank
引数の違いについて解説しました!
null
引数は「テーブル」に対する設定を行う引数であり、blank
引数は「フォーム」、特にフォームでの妥当性の検証に対する設定を行う引数となります。この違いを理解した上で、null
引数と blank
引数を指定するようにしましょう!