WizardMixin — multi-step form state machine

3 steps with browser-back-safe state. Refresh on step 2 → still on step 2 with values intact. Each step is a regular Django Form — WizardMixin handles navigation + validation + per-step rendering.

Account

step 1 of 3

The whole pattern

from djust.wizard import WizardMixin

class SignupWizard(WizardMixin, LiveView):
    wizard_steps = [
        {'name': 'account', 'title': 'Account', 'form_class': AccountForm},
        {'name': 'profile', 'title': 'Profile', 'form_class': ProfileForm},
        {'name': 'review',  'title': 'Review'},
    ]

    def on_wizard_complete(self, step_data):
        # step_data['account']['email'], step_data['profile']['display_name'], ...
        User.objects.create_user(**step_data['account'], **step_data['profile'])

Each step is a Django Form class. WizardMixin pre-renders field_html with dj-input/dj-change wiring (per wizard_input_event), tracks step_data across the wizard, and routes dj-submit="next_step" to advance only when the current step's form validates.

Refresh in any step → still on that step with values intact (state survives via the LiveView session backend, not browser local-storage). Browser back → previous step, values intact. wizard_rendered_fields opt-in skips rendering of fields outside the current step for further perf.