自動化無しに生活無し

WEBとかAIとかLinux関係をひたすら書く備忘録系ブログ

Djangoで数値型もしくはUUID型等のフィールドに、クライアント側から未入力を許可するにはnull=Trueとblank=Trueのオプションを

thumbnail

タイトルの通り。

基本的な話として、blankとは空文字列のこと。だから文字列型扱いになる。一方でnullはPythonで言うとNoneであり、型は無い。

よってblank=Trueのフィールドオプションが許されるのは、CharField等の文字列型系のフィールドのみで、IntegerFieldUUIDFieldには許されない。

と思われがちだが、それは半分誤解である。実は下記の指定は正しい。

dt          = models.DateTimeField(verbose_name="日時",null=True,blank=True)

このモデルフィールドは、未入力が許可される。その仕組みについて解説する。

null=Trueとblank=Trueの組み合わせと結果

フィールド null=Trueだけ blank=Trueだけ null=Trueとblank=True 未指定
CharField クライアントのフォーム未入力不可(バリデーション必ずNG) 未入力可(空文字列として扱う) 未入力の場合、null(None)扱い 入力必須
IntegerField クライアントのフォーム未入力不可(バリデーション必ずNG) マイグレーションすらできない 未入力の場合、null(None)扱い 入力必須
UUIDField クライアントのフォーム未入力不可(バリデーション必ずNG) マイグレーションすらできない 未入力の場合、null(None)扱い 入力必須
DateTimeField クライアントのフォーム未入力不可(バリデーション必ずNG) マイグレーションすらできない 未入力の場合、null(None)扱い 入力必須
ManyToManyField 効果なし 未入力可 null=Trueは効果なしなので警告 入力必須

null=Trueだけ

クライアントからのフォーム未入力は空文字として扱われる。故に、null=Trueだけとなるとクライアントのフォームの未入力は許可されない。

フォーム未入力不可なのは管理サイトでも同様ではあるが、サーバーサイドで直接コードからnullを指定して挿入することはできる。

しかし用途が限られるため、未入力を許可したいのであれば、後述のnull=Trueblank=Trueを組み合わせるやり方が妥当である。入力必須にしたいだけであれば未指定でOK。

blank=Trueだけ

繰り返しになるがblankとは空の文字列のことである。

CharFieldblank=Trueを指定すると空文字列として扱われる。

故にCharField等の文字列型系のフィールドであれば問題はないが、IntegerFieldUUIDField等の空文字列の入力を許さないフィールドではblank=Trueだけの指定はマイグレーションエラーになる。

null=Trueとblank=True

空文字列が許可されないフィールド(IntegerField、DateTimeFieldなど)でもフォームの未入力が許可される。ただし、その場合そのままテンプレートに表示すると、『None』と表示される

もし、Noneの表示ではなく、別の表記にしたい場合は、テンプレートのdefaultフィルタを使用する。

{{ topic.dt|default:"時刻未指定" }}

注意したい点は、CharFieldの場合、null=Trueblank=Trueを組み合わせると、Noneとして扱われる点にある。モデルのフィールドオプションでdefault=""と指定してもNoneとして扱われる。

そのため、CharFieldで未入力時のNoneと表示される問題はnull=Trueの指定をしないようにするか、あるいはdefaultフィルタで対処する。

いずれにしても、null=Trueblank=Trueの組み合わせで、DateTimeFieldやIntegerFieldにて、クライアント側から未入力ができるという余地が生まれる。selectタグでもvalue属性値を空文字列を選ぶことができる。

<select name="category">
    <option value="">未分類</option>
    {% for category in categories %}
    <option value="{{ category.id }}">{{ category.name }}</option>
    {% endfor %}
</select>

この選択を許可するメリットは、未分類などのカテゴリを前もって作っておき、loaddataコマンドを使ってDBへリストアしなくてもよいことにある。

未指定

入力必須になる。Charfieldの場合も未入力は許可されない。当然サーバーサイドのコードからも入力は必須になるため、null=Trueだけの場合と違ってどのような場合でも値が入る。

【例外】ManyToManyFieldはnullは意味なし

ManyToManyFieldの場合に限ってnull=Trueの指定は効果がない。

もし、未入力化としたい場合は、blank=Trueのみとする。

これはManyToManyFieldの仕様を考えるとわかる。

結論

Foreignkeyで繋がっている主キーがUUID型、もしくは数値型の場合にも同様にblank=Truenull=Trueを合わせて指定する。

こうすることで、カテゴリの指定をせず、Null(Python上のNone)として扱うことができる。後はテンプレート側から、defaultフィルタを使うと良いだろう。

スポンサーリンク

シェアボタン

Twitter LINEで送る Facebook はてなブログ