// the find
django-commons/django-unicorn
The magical reactive component framework for Django ✨
django-unicorn adds Livewire/Phoenix-LiveView-style reactive components to Django templates: you write a normal Django template plus a Python view class, and the library wires up AJAX calls and DOM diffing so parts of the page update without a full reload or a separate JS framework. It's aimed at Django shops that want form-heavy CRUD interactivity (validation, polling, loading states) without standing up React/Vue and a JSON API.
Progressive enhancement is the actual architecture, not a buzzword: the server renders full HTML first and JS binds on top, so first paint and SEO aren't held hostage by a client bundle. The feature set covers the stuff people actually build - Django-form-based validation, dirty-state tracking, loading indicators, polling, scroll-triggered visibility - without reaching for extra packages. There's a real test suite on both sides (pytest for the Python view/serializer logic, Jest for the morphdom/component JS), and a dedicated tests/views/action_parsers/test_security.py file, which at least signals they've had to think about the attack surface described below.
Every unicorn:click/model interaction is a round-trip AJAX call carrying the component's serialized state back and forth (see db.py/serializer.py) - fine for a form submit, noticeably worse than client-side state for anything rapid like keystroke-level updates or drag interactions, especially over higher-latency connections. The core mechanism is parsing method names and arguments out of client-submitted strings (call_method_parser.py) and dispatching them to Python methods on your view - that's a materially bigger attack surface than a normal Django POST handler, and the existence of a security-specific test file suggests this has already bitten them at least once. Per the contributor graph this is effectively a one-person project (adamghill authored nearly everything despite 17 listed contributors), which is a real bus-factor concern for something sitting in your request pipeline. And it locks interactivity to server-rendered Django templates - there's no clean path if you later need the same backend to serve a real SPA or mobile client, since the interaction model is specific to this library's template tags and serialization format.