Package: django-dynamic-form
Django Dynamic FormDjango Dynamic Form は、ユーザーによるフォームの入力、選択、変更などのイベントを検知し、
各フィールドの表示/非表示、有効/無効の切り替えや選択肢の変更などのフォームの最新化を行います。Installation'dynamic_form'をINSTALLED_APPSに追加します。INSTALLED_APPS=[...'dynamic_form',]dynamic_form の URLconf をプロジェクトのurls.pyに追加します。urlpatterns=[...path('',include('dynamic_form.urls')),]HTML に script タグを追加します。{% load static %}<scripttype="text/javascript"src="{% static 'dynamic_form/js/dynamic-form.js' %}"></script>Quick startフォーム にDynamicFormMixinを継承させます。fromdjangoimportformsfromdynamic_form.formsimportDynamicFormMixinclassTestForm(DynamicFormMixin,forms.Form):...settings.pyにフォームへの.(ドット)区切りのモジュールパスと、フォームを一意に特定する文字列を定義します。DYNAMIC_FORM={'FORM_KEYS':{'sample_app.forms.TestForm':'test_form',},}フォーム最新化のトリガーとなるフィールドに、data 属性data-ddf-triggerを追加します。
属性値にはイベントの種類を表すTriggerEventTypesクラスのメンバー値を指定します。
詳細はTriggerEventTypesをご覧ください。fromdynamic_form.typesimportTriggerEventTypesclassTestForm(DynamicFormMixin,forms.Form):age=forms.IntegerField(label='年齢',widget=forms.NumberInput(attrs={'data-ddf-trigger':TriggerEventTypes.BLUR,}))表示/非表示、有効/無効の切り替えなど、フィールドに対する制御を定義します。
詳細はフィールド制御メソッドをご覧ください。classTestForm(DynamicFormMixin,forms.Form):age=forms.IntegerField(label='年齢',widget=forms.NumberInput(attrs={'data-ddf-trigger':TriggerEventTypes.BLUR,}))consent=forms.BooleanField(label='保護者同意',help_text='未成年の場合は保護者の同意が必要です。',)defis_hidden_consent(self):age=self.data.get('age','')returnint(age)>=20ifage.isdigit()elseTrueビューでフォームを生成し、render_form()メソッドの戻り値をテンプレートに渡します。
テンプレートに渡されたrender_form()メソッドの戻り値をformタグで囲み、methodをPOSTにします。classTestView(TemplateView):template_name='test_view.html'defget(self,request,*args,**kwargs):form=TestForm()context={'test_form':form.render_form(),}returnself.render_to_response(context)test_view.html<formmethod="post">{% csrf_token %}
    {{ test_form }}<inputtype="submit"value="Submit"/></form>DocumentationDynamicFormMixinクラス変数form_templateフォームの表示はテンプレートファイルによりカスタマイズできます。
このテンプレートにはformタグを含めません。
カスタマイズしたテンプレートファイルはform_templateで指定します。classTestForm(DynamicFormMixin,forms.Form):form_template='sample_app/sample_form.html'sample_app/sample_form.html{% for field in form.visible_fields %}<divclass="form-row"><divclass="form-label">{{ field.label }}</div><divclass="form-field">{{ field }}</div>{% if field.errors %}<divclass="form-error">{{ field.errors }}</div>{% endif %}</div>{% endfor %}do_dynamic_validateフォーム最新化のときに、バリデーションを実施するかを指定します。
デフォルトはFalseです。classTestForm(DynamicFormMixin,forms.Form):do_dynamic_validate=Trueフィールド制御メソッドフィールド制御メソッドは、各フィールドの表示/非表示、有効/無効の切り替えや選択肢の変更などを制御します。
制御が必要なフィールドの、必要なメソッドのみを定義します。
フォームの入力内容はself.dataからアクセスできますが、未入力のフィールドなど値がself.dataに含まれない可能性を考慮する必要があります。制御できる項目は以下のとおりです。is_hidden_<field_name>()フィールドを非表示にするかの真偽値を返します。Trueを返した場合、フィールドのrequiredがFalseに、 ウィジェットがdjango.forms.HiddenInputとなります。is_disabled_<field_name>()フィールドを無効にするかの真偽値を返します。Trueを返した場合、フィールドのdisabledがTrueに、requiredがFalseとなります。is_required_<field_name>()フィールドを必須にするかの真偽値を返します。Trueを返した場合、フィールドのrequiredがTrueとなります。set_queryset_<field_name>()フィールドに設定するquerysetを返します。ModelChoiceFieldに対して使用します。defset_queryset_task(self):selected_member=self.data.get('member')returnTask.objects.filter(id=selected_member)set_choices_<field_name>()フィールドに設定するchoicesを返します。ChoiceFieldに対して使用します。defset_choices_fruits(self):return[(1,'apple'),(2,'banana'),(3,'melon'),]TriggerEventTypesTriggerEventTypesでは、フォーム最新化のトリガーとなるイベントを定義しています。
フィールドのdata-ddf-trigger属性の属性値に指定します。BLURフィールドからblurイベントが発生した場合にフォームを最新化します。CHANGEフィールドからchangeイベントが発生した場合にフォームを最新化します。CLICKフィールドからclickイベントが発生した場合にフォームを最新化します。DOUBLE_CLICKフィールドからdblclickイベントが発生した場合にフォームを最新化します。INPUTフィールドからinputイベントが発生した場合にフォームを最新化します。KEY_UPフィールドからkeyupイベントが発生した場合にフォームを最新化します。KEY_DOWNフィールドからkeydownイベントが発生した場合にフォームを最新化します。SELECTフィールドからselectイベントが発生した場合にフォームを最新化します。SettingsDjango Dynamic Form の設定はDYNAMIC_FORMという名前で指定します。DYNAMIC_FORM={'FORM_KEYS':{'sample_app.forms.TestForm':'test_form',},}FORM_KEYSフォームへの.(ドット)区切りのモジュールパスと、フォームを一意に特定する文字列を定義します。
この文字列はHTML上にdata-form-key属性の属性値として設定されます。モジュールパスは__class__.__module__と__class__.__name__を.(ドット)区切りで連結した文字列です。