SlideShare a Scribd company logo
1 of 97
Download to read offline
理解して使いこなすDjangoのForm機能
きゅうたつ(KyutatsuNishiura)
1
お前誰よ
きゅうたつ(Kyutatsu)
株式会社日本システム技研(JSL)所属
Webエンジニア
Python,Django,AWS
2
トークの対象者
Formは使ったことがあるが、既存コードをコピペして雰囲気でやっている。
いざ自分で実装しようとすると手が動かない.
公式DocumentのForm関連の項目を読むのが苦痛
3
こんな登録フォームがあったとします
お仕事の作業内容を、開始,終了時刻を登録するフォーム.
開始時刻の方には,6時〜23時までしか入力できないValidationがついている.
4
Q:こんな修正要望があったら?1/2
5
Q:こんな修正要望があったら?2/2
要望2.終了時刻の方にも、開始時刻と同じく6時〜23時の範囲チェックつけて!
要望3.開始時刻<終了時刻となってるようチェックして!
エラーメッセージはそれぞれのフィールドの上に出して!
6
目標
公式ドキュメントを読んで、手を動かせる.
作業量を見積もることができる.
そんなトークにしたいと思っています.
7
もくじ
まえおき
0章.準備編:FormをDjangoshellを使ってさわろう
1章.構造編:Formを構成する要素
2章.フロント編:HTMLをレンダリング
3章.バリデーション編:値をチェック
4章.便利な機能:FormSetでFormをたくさん並べよう! 8
9
初心者にとってFormの厄介なところ
複数のクラスが関わってくる。
modelやtemplate,validatorなど、複数の要素が絡んでくる。
パラメータなどを変更できるポイントが多い。
「ラベルを変えたい」だけでも、変更可能な場所が何箇所もある...
10
Formの構成要素をさわって動かしてみて理解する.
11
0章.Djangoshellを使おう
1.Djangoshellへの入り方
2.Templateへのレンダリングをshellから確認
12
0章.Djangoshellの入り方
$ python manage.py shell

...省略...

(InteractiveConsole)

>>> 

参照できるfield、ヘルプをその場で見れる。
テストコードを書くハードルが下がる.
13
0章:Templateへのレンダリングをshellから確認
formの定義
class NameForm(forms.Form):

name = forms.CharField()

インスタンス化
>>> form = NameForm()

14
0章:Templateへのレンダリングをshellから確認
DjangoTemplateLanguageでのレンダリング
カギカッコのアクセスはTemplateではドットで行う。
メソッドはコールされる。
最終的に__str__()される。
shellで出力結果を手軽に確認するにはprint()すればOK.
https://docs.djangoproject.com/ja/3.2/topics/templates/#variables

https://docs.djangoproject.com/ja/3.2/ref/templates/language/#variables
15
0章:Templateへのレンダリングをshellから確認
カギカッコのアクセスはドットで行う。
Template上でnameフィールドをレンダリング.
{{ form.name }}

↓
<input type="text" name="name" required id="id_name">

shell上で同じことをする場合.
最終的に__str__()される。->printを呼ぶ。
>>> print(form['name']) # []を使ったアクセス 

<input type="text" name="name" required id="id_name">
 16
0章:Templateへのレンダリングをshellから確認
メソッドはコールされる。
Template上でnameフィールドのラベルをレンダリング.
{{ form.name.label_tag }}
↓
<label for="id_name">Name:</label>

shellで同じことをする場合
最終的に__str__()される。->printを呼ぶ。
>>> print(form['name'].get_label()) # 関数呼び出し

<label for="id_name">Name:</label>
 17
1章.構造編:Formを構成する要素
18
1章.Formを構成する要素
以下のクラスが何者かをざっくり説明します。

詳細は後の方で解説します。
Form
Field
Widget
Validator
BoundField
19
1章.Formを構成する要素
以下のFormを例に説明します。
class MemberForm(forms.Form):

name = forms.CharField() # 名前

age = forms.IntegerField() # 年齢

FormにはFieldを定義できる。
Fieldは、デフォルトのwidgetとvalidatorを持っています.
20
1章.Formを構成する要素
Form
Field
Widget
Validator
BoundField
21
1章.Formを構成する要素:Widget
HTMLを生成するためのクラス.
form = MemberForm())

form.fields['name'].widget

<django.forms.widgets.TextInput at 0x7fe0fb4b04f0>
renderメソッドで、inputタグのようなウィジェットのHTMLを作ります。
form.fields['name'].widget.render('これがname属性', 'これがvalue')

'<input type="text" name="これがname属性" value="これがvalue">'

22
1章.Formを構成する要素
Form
Field
Widget
Validator
BoundField
23
1章.Formを構成する要素:Validator
受け取った値が条件を満たすかをチェックする.
form = MemberForm()

form.fields['name'].validators # listに入ってる.
[<django.core.validators.ProhibitNullCharactersValidator at 0x7fe0fc0700a0>]

24
ここまででおぼえておくこと
FormにはFieldを定義することができる
Fieldは以下のオブジェクトを持っている.
HTMLをrenderするWidget
値のチェック(バリデーション)をおこなうValidator
25
1章.Formを構成する要素
Fieldが持っているwidget,validatorsは、Built-inFieldclassesで確認できます。
https://docs.djangoproject.com/en/3.2/ref/forms/fields/#built-in-field-classes
26
1章.Formを構成する要素
Form
BoundField
Field
Widget
Validator
↓テンプレートでアクセスしているこれです。
{{ form.field_name }}

27
1章.Formを構成する要素:BoundFieldとField
https://docs.djangoproject.com/ja/3.2/ref/forms/api/#django.forms.BoundField
Fieldクラス
Formのattribueとして定義する。
BoundField
テンプレート上でのField関係のレンダリングはこのクラスが取りまとめる
FormのField名に[]アクセスしたときに作成される.-> form['name']
28
1章.Formを構成する要素:BoundFieldとField
Field
form.fields['name']

<django.forms.fields.CharField at 0x7fecdcbd7fa0>

BoundField
form['name']

<django.forms.boundfield.BoundField at 0x7fecdc936100>

29
1.Formを構成する要素まとめ
Form
Field
Widget→<input>のようなHTMLをつくる
Validator→値のチェックを行う.
BoundField→各FieldのHTMLへのレンダリングとりまとめる.
30
2章.フロント編:HTMLをレンダリング
1.BoundFieldの役割とできること
2.Widgetの役割とできること
31
2章.フロント編:BoundField
Field単位でHTMLレンダリングのロジックをまとめている。
32
2章.フロント編:BoundField
{{ form.field_name}}

form.<field_name>
これはBoundField。
HTMLレンダリングに必要な要素は,BoundFieldから基本的に取得します.
33
2章.フロント編:BoundField
BoundFieldはHTMLレンダリングに必要なメソッドや属性を持ってい
る.
https://docs.djangoproject.com/ja/3.2/ref/forms/api/#attributes-of-boundfield

利用可能な属性一覧はこちらの公式リンクから確認できます。
# labelタグを生成するメソッド

print(form['name'].label_tag())

<label for="id_name">Name:</label>

print(form['name'].id_for_label)

id_name

print(form['name'].name)

name

34
2章.フロント編:BoundField
BoundFieldはWidgetやErrorListクラスにHTMLレンダリングを任せて
いる.
BoundFieldをprintすると,widgetによりinputタグがでている
print(form['name'])

<input type="text" name="name" required>

error自体はFormクラスがまとめている。( form.errors )
ul タグの作成は、ErrorListクラスが行っている。
BoundFieldは、Formクラスから自分のFieldに対応するErrorListを取り出すだけ。
print(form['name'].errors)

<ul class="errorlist"><li>この項目は必須です。</li></ul>

35
2章.フロント編:BoundField
BoundFieldはField,Formそれぞれのインスタンス化する時の引数で変更を入れられる.
class MemberForm(forms.Form):

name = forms.CharField(label='変更したラベル')

form = MemberForm(auto_id='変更したID_%s')

print(form['name'].label_tag())

<label for="変更したID_name">変更したラベル:</label>

36
2章.フロント編:BoundField
Formのインスタンス化時に設定.

https://docs.djangoproject.com/ja/3.2/ref/forms/api/#configuring-form-elements-html-id-
attributes-and-label-tags
Fieldの引数

https://docs.djangoproject.com/ja/3.2/ref/forms/fields/#core-field-arguments
37
2章.フロント編:BoundFieldまとめ
BoundFieldは form['フィールド名'] にアクセスすることで作成される。
BoundFieldはField単位でのHTML出力をとりまとめている。
BoundFieldは、Field,Formそれぞれのインスタンス化時の引数によって変更を加えられ
る。
38
2章.フロント編:HTMLをレンダリング:Widget
https://docs.djangoproject.com/ja/3.2/ref/forms/widgets/
class MemberForm(forms.Form):

name = forms.CharField()

↓と同じ.
class MemberForm(forms.Form):

name = forms.CharField(

widget=forms.TextInput,

)

39
2章.フロント編:Widgetの差し替え
<input> などの要素をレンダリングします。
組み込みのwidgetが複数用意されています。
差し替えることで生成されるHTMLタグを簡単に変更できます.
自分でカスタムwidgetを定義することも可能です。
40
2章.フロント編:Widgetの差し替え
Formの定義
class MemberForm(forms.Form):

name = forms.CharField()

form['フィールド名'] はBoundFieldです。

これをprintすると、BoundFieldからWidgetのrenderがよばれ,HTMLが作られます。
form = MemberForm()

print(form['name'])

<input type="text" name="name" required id="id_name">

CharFieldのデフォルトwidget(TextInput)によりinputタグが作成される.
41
2章.フロント編:Widgetの差し替え
Formの定義
class MemberForm(forms.Form):

name = forms.CharField(widget=forms.Textarea) # TexInput-> Textarea

form['フィールド名'] はBoundFieldです。
form = MemberForm()

print(form['name'])

<textarea name="name" cols="40" rows="10" required id="id_name">

</textarea>

input->textareaタグに変更された。
42
2章.フロント編:Widgetの差し替え
HTMLタグのattributeを差し替えることができます。
widgetにはattr引数でdictを渡します。
class MemberForm(forms.Form):

name = forms.CharField(

# inputタグにclassを設定.

widget=forms.TextInput(attrs={'class': 'user-defined-attr'}))

form = MemberForm()

print(form['name'])

# クラスが設定された!

<input type="text" name="name" class="user-defined-attr" required id="id_name">

TextInputwidgetに渡したattrにより、printしたHTMLタグにclass属性が追加されてい
る.
43
2章.フロント編:Widgetはテンプレートを持つ
例:TextInputクラスのソースコード上の定義
class TextInput(Input):

input_type = 'text'

template_name = 'django/forms/widgets/text.html'

django/forms/widgets.py より抜粋.
{% include "django/forms/widgets/input.html" %}

/django/forms/templates/django/forms/widgets/text.html より。
44
2章.フロント編:Widgetはテンプレートを持つ
<input type="{{ widget.type }}"

name="{{ widget.name }}"i

{% if widget.value != None %}

value="{{ widget.value|stringformat:'s' }}"

{% endif %}

{% include "django/forms/widgets/attrs.html" %}>

/django/forms/templates/django/forms/widgets/input.html より改行などを加えて
抜粋。
45
2章.フロント編:Widgetまとめ
Widgetクラスはテンプレート+レンダリングのロジックを再利用可能な形でまとめてい
る。
WidgetのrenderメソッドはBoundFieldから呼ばれて利用される。
46
2章のまとめ
Widgetは <input> のようなFormの部品を定義している。
BoundFieldはField単位のHTMLレンダリングの取りまとめ役.
BoundFieldはwidgetやErrorListクラスにおねがい して、タグを丸ごとレンダリングす
ることもある.
47
3章.バリデーション編:値をチェック
1.validationの結果:データorエラー
2.エラーを構成するクラス
i.ErrorDict
ii.ErrorList
iii.ValidationError例外
3.validationの方法
i.Form.cleanで複数Fieldのチェック
ii.validatorを使ってひとつのFieldをチェック
iii.ModelFormのvalidation
48
3章.バリデーション編:validationの結果
class JslMemberForm(forms.Form):

name = forms.CharField() # 名前

age = forms.IntegerField() # 年齢

1.Validation成功->form.cleaned_dataに整形された値が入る.
2.Validation失敗->エラーがform.errorsにまとめられる.
49
3章.バリデーション編:validation成功
form.cleaned_data (dict)に「cleanされた」値が入る。
form = JslMemberForm({'name': 'たろう ', 'age': '20'})

form.is_valid()

Out[69]: True

form.cleaned_data

Out[70]: {'name': 'たろう', 'age': 20}

nameは後ろのスペースが除去されている
ageはint型に変更されている.
50
3章.バリデーション編:validation失敗
validationに失敗(エラーが発生)すると、 form.errors にエラーがまとめられる.
form = JslMemberForm({'name': '', 'age': 'にじゅっさい'})

form.is_valid()

Out[72]: False

form.errors

Out[73]: {'name': ['This field is required.'], 'age': ['Enter a whole number.']}

51
3章.バリデーション編:エラーを構成するクラス
1.ErrorDict
2.ErrorList
3.ValidationError例外
52
3章.バリデーション編:エラーを構成するクラス
form.errors

Out[73]: {'name': ['This field is required.'], 'age': ['Enter a whole number.']}

53
3章.バリデーション編:ErrorDictクラス
print(form.errors)

<ul class="errorlist">

<li>name<ul class="errorlist"><li>This field is required.</li></ul></li>

<li>age<ul class="errorlist"><li>Enter a whole number.</li></ul></li>

</ul>

__str__ メソッドでas_ul()を呼ぶようになっており,エラーメッセージのHTMLを作る
※ 一部改行とインデントを加えて表示.
54
3章.バリデーション編:ErrorListクラス
再掲
form.errors

Out[73]: {'name': ['This field is required.'], 'age': ['Enter a whole number.']}

ErrorDictのvalue部分はlistに見えるが、実際はErrorListと言うクラス.
form.errors['name']

Out[74]: ['This field is required.']

print(form.errors['name'])

<ul class="errorlist"><li>This field is required.</li></ul>

__str__ メソッドでas_ul()を呼ぶようになっており,エラーメッセージのHTMLを作る
55
3章.バリデーション編:ErrorListクラス
ポイント: form['name'] はBoundField.
Form._error から自分のFieldに属するエラーを引き出してきている.
print(form['name'].errors)

<ul class="errorlist"><li>この項目は必須です。</li></ul>

BoundFieldのソースコード↓
django/forms/boundfield.py
56
3章.バリデーション編:ValidationErrorr例外
form.errors['name']

Out[74]: ['This field is required.']

ErrorListクラスはValidationError例外を保持している.
Validationの失敗でraiseされるのは、全てこのValidationError例外.
form.errors['name'].data

Out[84]: [ValidationError(['This field is required.'])]

57
3章.バリデーション編:ValidationErrorr例外
formでvalidationをするときにraiseすることになっている例外.
formには、発生したValidationErrorをまとめる仕組みが実装されている。
58
3章.バリデーション編:ValidationError例外
https://docs.djangoproject.com/en/3.2/ref/forms/validation/#raising-validationerror
書き方のベストプラクティスという項目があるので、一読しておくと良いともいます.
59
3章.バリデーション編:エラーを構成するクラスまとめ
この二つは自らをHTMLとしてレンダリングすることができる.
ErrorDict: form.errors に入っている。
ErrorList:ErrorDictのvalue.
3.ValidationError例外
formでのvalidation失敗時にraiseする例外.
60
3章.バリデーション編:validationの方法
1.Form.cleanで複数Fieldのチェック
2.validatorを使ってひとつのFieldをチェック
61
3章.Validationは複数のステップで呼ばれる
https://docs.djangoproject.com/ja/3.2/ref/forms/validation/
Form
clean()
clean_<fieldname>()
Field
to_python()
validate()
run_validators()
Field.validators:listのvalidatorを順番に実行...
62
3章.Form.clean():複数Fieldをvalidateする
https://docs.djangoproject.com/ja/3.2/ref/forms/validation/#cleaning-and-validating-
fields-that-depend-on-each-other
開始時刻(start_at)と終了時刻(finish_at)をsubmitするFormを考える。
開始時刻<終了時刻となるようチェック。
このような場合、Validationはcleanメソッドに記述する.
63
3章.Form.clean():複数Fieldをvalidateする
class WorkTimeForm(forms.Form):

start_at = forms.DateTimeField()

finish_at = forms.DateTimeField()

def clean(self):

cleaned_data = super().clean()

start_at = cleaned_data.get("start_at")

finish_at = cleaned_data.get("finish_at")

if finish_at and start_at and finish_at <= start_at:

raise forms.ValidationError("終了時刻は開始時刻より後にしてください",

code='work_time_order')

64
3章.Form.clean():複数Fieldをvalidateする
form = WorkTimeForm({"start_at": "2020-01-02 08:00:00",

"finish_at": "2020-01-01 17:30:00"})

form.errors

{'__all__': ['終了時刻は開始時刻より後にしてください']}

finish_at<start_atとなるようなデータを渡してerrorsを見ると、エラーが出ている.
特定のFieldに結びついていないため、ErorrsDictのkeyは** __all__ **となっている.
65
3章. __all__ keyのエラーはform.non_field_errors()
で取得できる.
form.non_field_errors()

Out[101]: ['終了時刻は開始時刻より後にしてください']

print(form.non_field_errors())

<ul class="errorlist nonfield"><li>終了時刻は開始時刻より後にしてください</li></ul>

66
3章.key: __all__ のエラーはform.non_field_errors()
で取得できる.
テンプレートでは下のように書くと同じ意味になる.
{{ form.non_field_error }}

↓
<ul class="errorlist nonfield"><li>終了時刻は開始時刻より後にしてください</li></ul>

67
3章.form.add_errorで各Fieldにエラーメッセージをセッ
トする
https://docs.djangoproject.com/ja/3.2/ref/forms/validation/#cleaning-and-validating-
fields-that-depend-on-each-other
Form.add_errorsメソッドを呼ぶ.
class WorkTimeForm(forms.Form):

# .........(省略)...........

def clean(self):

# .......(省略).......

if finish_at <= start_at:

self.add_error('start_at', forms.ValidationError('開始時刻のエラー'))

self.add_error('finish_at', forms.ValidationError('終了時刻のエラー'))

68
3章.form.add_errorで各Fieldにエラーメッセージをセッ
トする
再掲.raiseValidationErrorした場合.
form.errors

{'__all__': ['終了時刻は開始時刻より後にしてください']}

修正後:add_errorを使った場合.
form = WorkTimeForm({"start_at": "2020-01-02 08:00:00",

"finish_at": "2020-01-01 17:30:00"})

form.errors

Out[105]: {'start_at': ['開始時刻が×'], 'finish_at': ['終了時刻が×']}

69
3章.form.add_errorで各Fieldにエラーメッセージをセッ
トする
それぞれのFieldに属しているので、レンダリングでエラーメッセージをFieldの隣に配置
するのに役立つ.
form['start_at'].errors

Out[107]: ['開始時刻が×']

復習:↑はBoundFieldが、formの_errorsから自分のfieldに出ているエラーを取得することで
表示している。
70
3章.バリデーション編
3.validationの方法
i.Form.cleanで複数Fieldのチェック
ii.validatorを使ってひとつのFieldをチェック
iii.ModelFormのvalidation
71
3章.バリデーション編:validatorでひとつのFieldをチェッ
ク
Form
clean()
clean_<field名>()
Field
to_python()
validate()
run_validators()
Field.validators:listのvalidatorを順番に実行...
72
3章.validatorの定義1/4
https://docs.djangoproject.com/en/3.2/ref/validators/
ドキュメントがFormとは別の場所にある。
Djangoでのvalidatorは以下のようなものです。
callableである.
引数を一つとる.
特定の条件を満たさない時、ValidationError例外をraiseする.
73
3章.validatorの定義2/4
from django.core.exceptions import ValidationError
def validate_even(value):

if value % 2 != 0:

raise ValidationError('これは偶数ではありません!')

https://docs.djangoproject.com/ja/3.2/ref/validators/を参考に記述.
単なる関数(など)なので、再利用性が高い。
74
3章.validatorの定義3/4
>>> validate_even(2)

# 何も返さない。(None)

奇数(3)を与えると、ValidationErrorをraiseする。
>>> validate_even(3)

...省略...

django.core.exceptions.ValidationError: ['これは偶数ではありません!']

75
3章.validatorの定義4/4
class NumberForm(forms.Form):

even = forms.IntegerField(validators=[validate_even])

form = NumberForm({'even': '3'})

form.errors

Out[37]: {'even': ['これは偶数ではありません!']}

76
3章.build-inのValidatorクラス
https://docs.djangoproject.com/en/3.2/ref/validators/#built-in-validators
built-inのvalidatorは一度見ておくと良い。
パラメータを渡し、インスタンス化して使うことができる。
from django.core.validators import RegexValidator

start_with_jsl = RegexValidator(regex='^jsl.*', message='「jsl」から始めてください')

start_with_jsl('jsl00000') # OK

start_with_jsl('AAA00000') # NG!

# django.core.exceptions.ValidationError: ['「jsl」から始めてください']

77
3章.バリデーション編
3.validationの方法
i.Form.cleanで複数Fieldのチェック
ii.validatorを使ってひとつのFieldをチェック
iii.ModelFormのvalidation
78
3章.バリデーション編:値をチェック
1.validationの結果:データorエラー
2.エラーを構成するクラス
i.ErrorDict
ii.ErrorLis
iii.ValidationError例外
3.validationの方法
i.Form.cleanで複数Fieldのチェック
ii.validatorを使ってひとつのFieldをチェック
iii.ModelFormのvalidation
79
4章.便利な機能:FormSetでFormをたくさん並べよう!
80
4章.FormSet
https://docs.djangoproject.com/ja/3.2/topics/forms/formsets/

https://docs.djangoproject.com/ja/3.2/topics/forms/modelforms/#model-formsets
81
4章.FormSet
同じ種類のFormを複数並べる時に便利!
factory関数を使って簡単にFormSetインスタンスを作成できる.
通常のFormとほぼ同じように扱える。
82
4章.FormSet
formset_factoryとmodelformset_factoryがある。
既存のModelFormから、modelformset_factoryを使ってFormSetを作る例を紹介しま
す。
83
4章.FormSet
class Member(models.Model):

name = models.CharField(max_length=100)

age = models.IntegerField(null=True, blank=True)

class MemberModelForm(forms.ModelForm):

class Meta:

model = Member

fields = ('name',)

84
4章.FormSet
from django.forms import modelformset_factory

MemberFormSet = modelformset_factory(

model=Member,

form=MemberModelForm,
extra=5, # いくつ空のFormを並べるか。

)

これだけ!
85
4章.FormSet:Viewでの使い方
通常のモデルフォーム
# 空

form = MemberModelForm()

# データあり

form = MemberModelForm(request.POST)

↓
# 空

form_set = MemberFormSet(queryset=Member.objects.none())

# データあり

form_set = MemberFormSet(request.POST, queryset=Member.objects.none()) 

querysetを指定すると、DB上のデータを投入したFormSetを表示できる(編集)
Model.objects.non()を指定すると、空のformsetができます(新規登録)
86
4章.テンプレートでは
https://docs.djangoproject.com/ja/3.2/topics/forms/modelforms/#using-the-formset-in-
the-template
<form method="POST">

{% csrf_token %}

<!-- 補助フィールド -->

{{ form_set.management_form }}

{% for f in form_set %}

{{ f }}

{% endfor %}

<input type="submit" value="SUBMIT!">

</form>

87
まとめ
とっつきにくいDjangoのForm機能ですが、個人的にはいくつかキーとなるポイントを知って
おくと、怖くなくなるのではないかと思います
djangoshellを使ってFormクラスやModelクラスと仲良くなるのはオススメ
Formクラスが含むそれぞれのオブジェクトの役割をイメージすると、ドキュメントが読
みやすくなる。
88
しゃべることのできなかったModelFormのvalidation.
89
3章.バリデーション編
3.validationの方法
i.Form.cleanで複数Fieldのチェック
ii.validatorを使ってひとつのFieldをチェック
iii.ModelFormのvalidation
90
3章.ModelFormとは
https://docs.djangoproject.com/ja/3.2/topics/forms/modelforms/
model定義
class Member(models.Model):

name = models.CharField(verbose_name='名前', max_length=100)

age = models.IntegerField(verbose_name='年齢')

Form定義
class MemberModelForm(forms.ModelForm):

class Meta:

model = Member

fields = ('name', 'age')

91
3章.Modelにもvalidatiorを設定できる.
class ProjectCode(models.Model):

jsl_code = models.CharField(

verbose_name='プロジェクトコード', max_length=7,

validators=[RegexValidator(regex='^jsl[0-9]{4}$')])

project_code = ProjectCode(jsl_code='jsl0')

project_code.full_clean()
django.core.exceptions.ValidationError: {'jsl_code': ['Enter a valid value.']}

92
Modelにもvalidatorを設定できる.
https://docs.djangoproject.com/ja/3.2/ref/models/instances/#validating-objects
https://docs.djangoproject.com/ja/3.2/ref/models/fields/#validators
Model:.full_clean()で以下を実行.
clean_fields()->Fieldsのvalidation
clean()
validate_unique()
93
ModelとModelFormにvalidatorを設定すると...
class ProjectCode(models.Model):

jsl_code = models.CharField(

max_length=7,

validators=[RegexValidator(regex='^jsl[0-9]{4}$', message='model側')])

class ProjectCodeModelForm(forms.ModelForm):

class Meta:

model = ProjectCode

fields = ('jsl_code', )

# Form由来は末尾1としてみる.

jsl_code = forms.CharField(

validators=[RegexValidator(regex='1$', message='Form側')])

94
ModelとModelFormにvalidatorを設定すると...
form = ProjectCodeModelForm({'jsl_code': 'jsl0000'})

form.errors

Out[14]: {'jsl_code': ['Form側']}

form = ProjectCodeModelForm({'jsl_code': '0001'})

form.errors

Out[12]: {'jsl_code': ['model側']}

95
ModelとModelFormにvalidatorを設定すると...
Model,Formどちらも満たさない場合.

Form側のメッセージしか表示されません.
form = ProjectCodeModelForm({'jsl_code': '00'})

form.errors

Out[16]: {'jsl_code': ['Form側']}

Model側でやっていたチェック(jsl...となること)のメッセージも出したければ

Form側に同じvalidatorを設定する必要があります.
class ProjectCodeModelForm(forms.ModelForm):

# ...省略....

validators=[

RegexValidator(regex='1$', message='Form側'),

RegexValidator(regex='^jsl[0-9]{4}$', message='Form側その2')])

96
ModelとModelFormにvalidatorを設定すると...
ModelForm側で設定した2つのバリデーション結果がerrorsに入っている。
form = ProjectCodeModelForm({'jsl_code': '00'})

form.errors

Out[28]: {'jsl_code': ['Form側', 'Form側その2']}

97

More Related Content

What's hot

MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法Tetsutaro Watanabe
 
マイクロサービスバックエンドAPIのためのRESTとgRPC
マイクロサービスバックエンドAPIのためのRESTとgRPCマイクロサービスバックエンドAPIのためのRESTとgRPC
マイクロサービスバックエンドAPIのためのRESTとgRPCdisc99_
 
DDDのモデリングとは何なのか、 そしてどうコードに落とすのか
DDDのモデリングとは何なのか、 そしてどうコードに落とすのかDDDのモデリングとは何なのか、 そしてどうコードに落とすのか
DDDのモデリングとは何なのか、 そしてどうコードに落とすのかKoichiro Matsuoka
 
Python 3.9からの新定番zoneinfoを使いこなそう
Python 3.9からの新定番zoneinfoを使いこなそうPython 3.9からの新定番zoneinfoを使いこなそう
Python 3.9からの新定番zoneinfoを使いこなそうRyuji Tsutsui
 
データベース設計徹底指南
データベース設計徹底指南データベース設計徹底指南
データベース設計徹底指南Mikiya Okuno
 
Apache Avro vs Protocol Buffers
Apache Avro vs Protocol BuffersApache Avro vs Protocol Buffers
Apache Avro vs Protocol BuffersSeiya Mizuno
 
こわくない Git
こわくない Gitこわくない Git
こわくない GitKota Saito
 
Rustに触れて私のPythonはどう変わったか
Rustに触れて私のPythonはどう変わったかRustに触れて私のPythonはどう変わったか
Rustに触れて私のPythonはどう変わったかShunsukeNakamura17
 
「GraphDB徹底入門」〜構造や仕組み理解から使いどころ・種々のGraphDBの比較まで幅広く〜
「GraphDB徹底入門」〜構造や仕組み理解から使いどころ・種々のGraphDBの比較まで幅広く〜「GraphDB徹底入門」〜構造や仕組み理解から使いどころ・種々のGraphDBの比較まで幅広く〜
「GraphDB徹底入門」〜構造や仕組み理解から使いどころ・種々のGraphDBの比較まで幅広く〜Takahiro Inoue
 
トランザクションスクリプトのすすめ
トランザクションスクリプトのすすめトランザクションスクリプトのすすめ
トランザクションスクリプトのすすめpospome
 
ドメインロジックの実装方法とドメイン駆動設計
ドメインロジックの実装方法とドメイン駆動設計ドメインロジックの実装方法とドメイン駆動設計
ドメインロジックの実装方法とドメイン駆動設計Tadayoshi Sato
 
がっつりMongoDB事例紹介
がっつりMongoDB事例紹介がっつりMongoDB事例紹介
がっつりMongoDB事例紹介Tetsutaro Watanabe
 
MongoDB〜その性質と利用場面〜
MongoDB〜その性質と利用場面〜MongoDB〜その性質と利用場面〜
MongoDB〜その性質と利用場面〜Naruhiko Ogasawara
 
モジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェースモジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェースHajime Yanagawa
 
Webアプリを並行開発する際のマイグレーション戦略
Webアプリを並行開発する際のマイグレーション戦略Webアプリを並行開発する際のマイグレーション戦略
Webアプリを並行開発する際のマイグレーション戦略Takayuki Shimizukawa
 
マイクロにしすぎた結果がこれだよ!
マイクロにしすぎた結果がこれだよ!マイクロにしすぎた結果がこれだよ!
マイクロにしすぎた結果がこれだよ!mosa siru
 
オブジェクト指向できていますか?
オブジェクト指向できていますか?オブジェクト指向できていますか?
オブジェクト指向できていますか?Moriharu Ohzu
 

What's hot (20)

MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法
 
マイクロサービスバックエンドAPIのためのRESTとgRPC
マイクロサービスバックエンドAPIのためのRESTとgRPCマイクロサービスバックエンドAPIのためのRESTとgRPC
マイクロサービスバックエンドAPIのためのRESTとgRPC
 
DDDのモデリングとは何なのか、 そしてどうコードに落とすのか
DDDのモデリングとは何なのか、 そしてどうコードに落とすのかDDDのモデリングとは何なのか、 そしてどうコードに落とすのか
DDDのモデリングとは何なのか、 そしてどうコードに落とすのか
 
Python 3.9からの新定番zoneinfoを使いこなそう
Python 3.9からの新定番zoneinfoを使いこなそうPython 3.9からの新定番zoneinfoを使いこなそう
Python 3.9からの新定番zoneinfoを使いこなそう
 
データベース設計徹底指南
データベース設計徹底指南データベース設計徹底指南
データベース設計徹底指南
 
Apache Avro vs Protocol Buffers
Apache Avro vs Protocol BuffersApache Avro vs Protocol Buffers
Apache Avro vs Protocol Buffers
 
gRPC入門
gRPC入門gRPC入門
gRPC入門
 
こわくない Git
こわくない Gitこわくない Git
こわくない Git
 
Rustに触れて私のPythonはどう変わったか
Rustに触れて私のPythonはどう変わったかRustに触れて私のPythonはどう変わったか
Rustに触れて私のPythonはどう変わったか
 
「GraphDB徹底入門」〜構造や仕組み理解から使いどころ・種々のGraphDBの比較まで幅広く〜
「GraphDB徹底入門」〜構造や仕組み理解から使いどころ・種々のGraphDBの比較まで幅広く〜「GraphDB徹底入門」〜構造や仕組み理解から使いどころ・種々のGraphDBの比較まで幅広く〜
「GraphDB徹底入門」〜構造や仕組み理解から使いどころ・種々のGraphDBの比較まで幅広く〜
 
トランザクションスクリプトのすすめ
トランザクションスクリプトのすすめトランザクションスクリプトのすすめ
トランザクションスクリプトのすすめ
 
キメるClojure
キメるClojureキメるClojure
キメるClojure
 
ドメインロジックの実装方法とドメイン駆動設計
ドメインロジックの実装方法とドメイン駆動設計ドメインロジックの実装方法とドメイン駆動設計
ドメインロジックの実装方法とドメイン駆動設計
 
がっつりMongoDB事例紹介
がっつりMongoDB事例紹介がっつりMongoDB事例紹介
がっつりMongoDB事例紹介
 
MongoDB〜その性質と利用場面〜
MongoDB〜その性質と利用場面〜MongoDB〜その性質と利用場面〜
MongoDB〜その性質と利用場面〜
 
モジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェースモジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェース
 
Webアプリを並行開発する際のマイグレーション戦略
Webアプリを並行開発する際のマイグレーション戦略Webアプリを並行開発する際のマイグレーション戦略
Webアプリを並行開発する際のマイグレーション戦略
 
Go入門
Go入門Go入門
Go入門
 
マイクロにしすぎた結果がこれだよ!
マイクロにしすぎた結果がこれだよ!マイクロにしすぎた結果がこれだよ!
マイクロにしすぎた結果がこれだよ!
 
オブジェクト指向できていますか?
オブジェクト指向できていますか?オブジェクト指向できていますか?
オブジェクト指向できていますか?
 

Similar to 理解して使いこなすDjangoのForm機能(2021 Django Congress発表資料)

JobScheduler Code Reading
JobScheduler Code ReadingJobScheduler Code Reading
JobScheduler Code ReadingShinobu Okano
 
OSSで楽に作るGo言語クライアントツール
OSSで楽に作るGo言語クライアントツールOSSで楽に作るGo言語クライアントツール
OSSで楽に作るGo言語クライアントツールTano Makoto
 
20160326 第10回 Rad Studio 勉強会@Osaka
20160326 第10回 Rad Studio 勉強会@Osaka20160326 第10回 Rad Studio 勉強会@Osaka
20160326 第10回 Rad Studio 勉強会@OsakaRyo Ohki
 
Robotium を使った UI テスト
Robotium を使った UI テストRobotium を使った UI テスト
Robotium を使った UI テスト健一 辰濱
 
Introduction to GNOME Translation (OSC2012 Tokyo/Spring)
Introduction to GNOME Translation (OSC2012 Tokyo/Spring)Introduction to GNOME Translation (OSC2012 Tokyo/Spring)
Introduction to GNOME Translation (OSC2012 Tokyo/Spring)Jiro Matsuzawa
 
元気にリモートワークを始める方法
元気にリモートワークを始める方法元気にリモートワークを始める方法
元気にリモートワークを始める方法Tsuyoshi Seino
 
Yidev201406.pub
Yidev201406.pubYidev201406.pub
Yidev201406.pubitoz itoz
 
ど素人向け エンジニア勉強会
ど素人向け エンジニア勉強会ど素人向け エンジニア勉強会
ど素人向け エンジニア勉強会YukiIwasaki2764
 
MTプラグイン入門以前
MTプラグイン入門以前MTプラグイン入門以前
MTプラグイン入門以前Hiroshi Yamato
 
[Okta x Jamf合同新年会] Okta Workflowsによるノーコード業務改善 〜Jamf APIを使ってMac端末情報を自動収集してみよう〜
[Okta x Jamf合同新年会] Okta Workflowsによるノーコード業務改善 〜Jamf APIを使ってMac端末情報を自動収集してみよう〜[Okta x Jamf合同新年会] Okta Workflowsによるノーコード業務改善 〜Jamf APIを使ってMac端末情報を自動収集してみよう〜
[Okta x Jamf合同新年会] Okta Workflowsによるノーコード業務改善 〜Jamf APIを使ってMac端末情報を自動収集してみよう〜Ryo Sasaki
 
SubversionとSugarsync
SubversionとSugarsyncSubversionとSugarsync
SubversionとSugarsyncHidenori Goto
 
Generating word clouds in python
Generating word clouds in pythonGenerating word clouds in python
Generating word clouds in pythonAyakaHonda1
 
恊働ロボットCOROの開発における形式的仕様の適用事例
恊働ロボットCOROの開発における形式的仕様の適用事例恊働ロボットCOROの開発における形式的仕様の適用事例
恊働ロボットCOROの開発における形式的仕様の適用事例Life Robotics
 
自分よりも技術力の高い会社に入社して感じたこと
自分よりも技術力の高い会社に入社して感じたこと自分よりも技術力の高い会社に入社して感じたこと
自分よりも技術力の高い会社に入社して感じたことSuzuki Masayuki
 
プログラミングを早くする方法
プログラミングを早くする方法プログラミングを早くする方法
プログラミングを早くする方法kazukiTakahashi18
 
Apps foroffice seminar 20130617 hands-on
Apps foroffice seminar 20130617 hands-onApps foroffice seminar 20130617 hands-on
Apps foroffice seminar 20130617 hands-onSeiji Noro
 
Visual Studio 2019 / Visual Studio Code + Live Shareではじめるモブ・プログラミング #vs2019
Visual Studio 2019 / Visual Studio Code + Live Shareではじめるモブ・プログラミング #vs2019Visual Studio 2019 / Visual Studio Code + Live Shareではじめるモブ・プログラミング #vs2019
Visual Studio 2019 / Visual Studio Code + Live Shareではじめるモブ・プログラミング #vs2019満徳 関
 
仕事でも Groovy を使おう!
仕事でも Groovy を使おう!仕事でも Groovy を使おう!
仕事でも Groovy を使おう!Oda Shinsuke
 

Similar to 理解して使いこなすDjangoのForm機能(2021 Django Congress発表資料) (20)

JobScheduler Code Reading
JobScheduler Code ReadingJobScheduler Code Reading
JobScheduler Code Reading
 
OSSで楽に作るGo言語クライアントツール
OSSで楽に作るGo言語クライアントツールOSSで楽に作るGo言語クライアントツール
OSSで楽に作るGo言語クライアントツール
 
20160326 第10回 Rad Studio 勉強会@Osaka
20160326 第10回 Rad Studio 勉強会@Osaka20160326 第10回 Rad Studio 勉強会@Osaka
20160326 第10回 Rad Studio 勉強会@Osaka
 
Robotium を使った UI テスト
Robotium を使った UI テストRobotium を使った UI テスト
Robotium を使った UI テスト
 
Introduction to GNOME Translation (OSC2012 Tokyo/Spring)
Introduction to GNOME Translation (OSC2012 Tokyo/Spring)Introduction to GNOME Translation (OSC2012 Tokyo/Spring)
Introduction to GNOME Translation (OSC2012 Tokyo/Spring)
 
元気にリモートワークを始める方法
元気にリモートワークを始める方法元気にリモートワークを始める方法
元気にリモートワークを始める方法
 
Yidev201406.pub
Yidev201406.pubYidev201406.pub
Yidev201406.pub
 
ど素人向け エンジニア勉強会
ど素人向け エンジニア勉強会ど素人向け エンジニア勉強会
ど素人向け エンジニア勉強会
 
MTプラグイン入門以前
MTプラグイン入門以前MTプラグイン入門以前
MTプラグイン入門以前
 
[Okta x Jamf合同新年会] Okta Workflowsによるノーコード業務改善 〜Jamf APIを使ってMac端末情報を自動収集してみよう〜
[Okta x Jamf合同新年会] Okta Workflowsによるノーコード業務改善 〜Jamf APIを使ってMac端末情報を自動収集してみよう〜[Okta x Jamf合同新年会] Okta Workflowsによるノーコード業務改善 〜Jamf APIを使ってMac端末情報を自動収集してみよう〜
[Okta x Jamf合同新年会] Okta Workflowsによるノーコード業務改善 〜Jamf APIを使ってMac端末情報を自動収集してみよう〜
 
SubversionとSugarsync
SubversionとSugarsyncSubversionとSugarsync
SubversionとSugarsync
 
鹿駆動
鹿駆動鹿駆動
鹿駆動
 
Generating word clouds in python
Generating word clouds in pythonGenerating word clouds in python
Generating word clouds in python
 
恊働ロボットCOROの開発における形式的仕様の適用事例
恊働ロボットCOROの開発における形式的仕様の適用事例恊働ロボットCOROの開発における形式的仕様の適用事例
恊働ロボットCOROの開発における形式的仕様の適用事例
 
自分よりも技術力の高い会社に入社して感じたこと
自分よりも技術力の高い会社に入社して感じたこと自分よりも技術力の高い会社に入社して感じたこと
自分よりも技術力の高い会社に入社して感じたこと
 
プログラミングを早くする方法
プログラミングを早くする方法プログラミングを早くする方法
プログラミングを早くする方法
 
Apps foroffice seminar 20130617 hands-on
Apps foroffice seminar 20130617 hands-onApps foroffice seminar 20130617 hands-on
Apps foroffice seminar 20130617 hands-on
 
Visual Studio 2019 / Visual Studio Code + Live Shareではじめるモブ・プログラミング #vs2019
Visual Studio 2019 / Visual Studio Code + Live Shareではじめるモブ・プログラミング #vs2019Visual Studio 2019 / Visual Studio Code + Live Shareではじめるモブ・プログラミング #vs2019
Visual Studio 2019 / Visual Studio Code + Live Shareではじめるモブ・プログラミング #vs2019
 
仕事でも Groovy を使おう!
仕事でも Groovy を使おう!仕事でも Groovy を使おう!
仕事でも Groovy を使おう!
 
Google Product
Google ProductGoogle Product
Google Product
 

Recently uploaded

Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。iPride Co., Ltd.
 
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...Toru Tamaki
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。iPride Co., Ltd.
 
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。iPride Co., Ltd.
 
Utilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native IntegrationsUtilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native IntegrationsWSO2
 
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)Hiroshi Tomioka
 
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Gamesatsushi061452
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイスCRI Japan, Inc.
 
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptxsn679259
 
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video UnderstandingToru Tamaki
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルCRI Japan, Inc.
 

Recently uploaded (11)

Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
 
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。
 
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
 
Utilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native IntegrationsUtilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native Integrations
 
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
 
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
 
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
 
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
 

理解して使いこなすDjangoのForm機能(2021 Django Congress発表資料)