[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f3rkn70drc4ikk":3},{"_id":4,"slug":5,"title":6,"subtitle":7,"kind":8,"cards":9,"tags":57,"categories":59,"source":61,"lang":64,"author":65,"audioState":68,"stats":69,"publishedAt":72,"renderer":73},"6abb0bceca21c797c7e9be20","django-nova-what-changed-when-i-put-the-library-behind-a-pub-0dd4a0f7","Django Nova: What Changed When I Put the Library Behind a Public Demo","Cache invalidation, async boundaries, and the work behind novademo.tech.","news",[10,12,17,22,27,32,37,42,47,52],{"headline":6,"body":7,"imageUrl":11,"sourceImageUrl":11},"https:\u002F\u002Fmedia2.dev.to\u002Fdynamic\u002Fimage\u002Fwidth=1200,height=627,fit=cover,gravity=auto,format=auto\u002Fhttps%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhpaictgooz3efsu7ecyo.png",{"headline":13,"body":14,"imageUrl":15,"images":16},"During the deployment of Django Nova’s public demo","During the deployment of Django Nova’s public demo, the application was already returning {\"status\": \"ok\"}. PostgreSQL, Redis, Memcached, and the web container were healthy. The same health endpoint through Nginx returned 404.","\u002Fapi\u002Fmedia\u002Fposts\u002Fdjango-nova-what-changed-when-i-put-the-library-behind-a-pub-0dd4a0f7\u002F1.webp",{"local":15},{"headline":18,"body":19,"imageUrl":20,"images":21},"That small failure was a useful reminder: a","That small failure was a useful reminder: a successful check proves something about the layer it reaches. It does not automatically prove that the next layer works. I have been learning the same lesson inside Django Nova.","\u002Fapi\u002Fmedia\u002Fposts\u002Fdjango-nova-what-changed-when-i-put-the-library-behind-a-pub-0dd4a0f7\u002F2.webp",{"local":20},{"headline":23,"body":24,"imageUrl":25,"images":26},"In my earlier architecture article, I focused on","In my earlier architecture article, I focused on duplicated validation and shared schemas. In the typing follow-up, I described the difficulty of putting a typed interface around Django’s dynamic metadata. Now there is a public application where readers can inspect and exercise some of those ideas:","\u002Fapi\u002Fmedia\u002Fposts\u002Fdjango-nova-what-changed-when-i-put-the-library-behind-a-pub-0dd4a0f7\u002F3.webp",{"local":25},{"headline":28,"body":29,"imageUrl":30,"images":31},"Getting there meant dealing with transactions, mutable cached","Getting there meant dealing with transactions, mutable cached objects, asynchronous execution, deployment, and recovery. It also meant being more precise about what Nova promises. A shared schema still needs boundaries","\u002Fapi\u002Fmedia\u002Fposts\u002Fdjango-nova-what-changed-when-i-put-the-library-behind-a-pub-0dd4a0f7\u002F4.webp",{"local":30},{"headline":33,"body":34,"imageUrl":35,"images":36},"Django Nova connects Django models with Pydantic schemas","Django Nova connects Django models with Pydantic schemas, query planning, caching, and optional integrations. Django’s ORM remains responsible for persistence.","\u002Fapi\u002Fmedia\u002Fposts\u002Fdjango-nova-what-changed-when-i-put-the-library-behind-a-pub-0dd4a0f7\u002F5.webp",{"local":35},{"headline":38,"body":39,"imageUrl":40,"images":41},"The original motivation is familiar: an application can","The original motivation is familiar: an application can repeat similar rules in a serializer, a form, a model, and a background task. As these entry points evolve, their behavior can drift. Shared schemas help, but the different validation layers still have work to do.","\u002Fapi\u002Fmedia\u002Fposts\u002Fdjango-nova-what-changed-when-i-put-the-library-behind-a-pub-0dd4a0f7\u002F6.webp",{"local":40},{"headline":43,"body":44,"imageUrl":45,"images":46},"In the current implementation, NovaModel.save() checks the selected","In the current implementation, NovaModel.save() checks the selected Pydantic schema, validates and converts Django fields, runs Model.clean(), checks uniqueness and model constraints, and then saves through Django. A failure stops the later stages.","\u002Fapi\u002Fmedia\u002Fposts\u002Fdjango-nova-what-changed-when-i-put-the-library-behind-a-pub-0dd4a0f7\u002F7.webp",{"local":45},{"headline":48,"body":49,"imageUrl":50,"images":51},"One detail matters more than it initially appears","One detail matters more than it initially appears: a value returned by Django’s field.clean() must be assigned back to the instance before model-level validation runs. Otherwise, a later validator can inspect the original value even though field conversion succeeded.","\u002Fapi\u002Fmedia\u002Fposts\u002Fdjango-nova-what-changed-when-i-put-the-library-behind-a-pub-0dd4a0f7\u002F8.webp",{"local":50},{"headline":53,"body":54,"imageUrl":55,"images":56},"There are also write paths that bypass this","There are also write paths that bypass this sequence. QuerySet.update(), bulk_create(), and bulk_update() do not call model save(). Database constraints remain necessary, particularly when writes race.","\u002Fapi\u002Fmedia\u002Fposts\u002Fdjango-nova-what-changed-when-i-put-the-library-behind-a-pub-0dd4a0f7\u002F9.webp",{"local":55},[58],"dev",[60],"Technology",{"name":62,"url":63},"Dev.to","https:\u002F\u002Fdev.to\u002Fartem7898\u002Fdjango-nova-what-changed-when-i-put-the-library-behind-a-public-demo-3fpj","en",{"handle":66,"displayName":67},"spots","Spots","queued",{"views":70,"likes":71,"saves":71,"shares":71,"completions":71,"opens":71,"skips":71,"depthSum":71},3,0,"2026-09-29T00:52:30.240Z","local"]