Replies: 3 comments 5 replies
-
Hey @tanssinet, there's a lot of info in there, and I'd probably need to re-read it a few times to fully understand all the points you're considering, but here are some ways how I structure Django/HTMX/AlpineJS app:
With these in mind, here is how I would approach some of the issues you're mentioning:
Hope this helps! |
Beta Was this translation helpful? Give feedback.
-
Another take at this (and there are as many takes on this as there are developers!) from me. I am not a big fan of splitting my business rules between the backend and frontend. I think it quickly leads to messy and hard to maintain codebases, where every features needs to be implemented twice; once in the backend, and once in the frontend. A way around this is to say that, yes, we will need a backend no matter what. So let's put our business logic, state handling, and effort there, and try to keep the frontend as minimal as possible. Django-components allows you to build sites like that if you want. Without going into details about your specific case, and given the above "philosophy" around where to focus ones effort:
Advantages:
As I said, there are as many opinions on this as there are developers, but I wanted to add my take. |
Beta Was this translation helpful? Give feedback.
-
Hey @tanssinet, In case it's useful:
|
Beta Was this translation helpful? Give feedback.
-
I built a mid-sized Django app (150+ views) alone in few months, and you just cannot beat the productivity. In this case the user experience with traditional web app was good enough, and it was more important to be fast than to have a "modern" feel.
But some parts got unnecessarily hairy and complex. One page includes (among other things) two-level "nested" inline model formsets, where the lowest leel has multiple instances of the same autocomplete fields. Basically it is list of lists of values selected by autocomplete. I only send the parent entity (with all the children) to backend when the root entity create or update is complete.
And now I need to create an even more complex version of this same page.
I have used several frontend frameworks, but try to use them as little as possible to keep my productivity up. I have built a component library for a customer using Angular 1.x so I have some understanding how to approach component libraries.
I have tried to use component approach in my project as much as possible, but Django wthout django-componts does not make it easy. Currently, I have abstract and generic "autocomplete component" (based on Bloodhound.js/Typeahead.js) and have then "subclassed" ths component for various types of entities I need to search for, with a corresponding REST API for each autocomplete. Autocomplete components (both the generic and model-specific ones) are currently crispy form Fields, but then I build a JSON object inside the level-1 formset of the parent.
I was inspired by the video below, so my idea would be to build the new page with a combination of django-components/Alpine.js/HTMX, possibly using crispy forms there as well.
https://www.youtube.com/watch?v=3GObi93tjZI
I really like the idea that django-components/Alpine.js/HTMX are small libraries that work well together, but I am struggling currently to understand how they should be working together, and how I should structure my application.
So let's start with the autocomplete selection component. In my case, I am searching for a performer, i.e. a singer or orchesra.
The user should get the autocomplete experience, but having a REST API makes things unnecessarily complex when we have HTMX. There is django-htmx-autocomplete library, but that appears to have it's own approach to components that does not work that well with django-components nor with standard django forms or crispy forms. So potentially I would need to rewrite a component similar to it, but using djanco-components model.
As I need to add multiple performers (and later multiple groups of performers, and even later multiple events containing multiple groups of performers), I must have multiple copies of the component on the page -- although potentially only when editing -- so they need to have a unique identifier. One approach is to pass a unique identifier from the parent, this has the benefit that the parent then knows the identity and can use it for data. Apparently Alpine.js has $id magic property that could be used to generate the identifier. But if I do that, how do I reference the selected vaue from the parent component?
The biggest issue when building components is communication between components. Maybe the term "component" is too abstract and generic. Some components are more like "fields" (such as autocomplete), whereas others are more like "forms" (collections of related fields). For field-like components such as autocomplete, it makes sense that the frontend keeps the state until the parent component wants to save the data.
Another aspect related to HTMX is data permanence. I think nobody wants to give up the idea that servers are stateless. But sometimes the data is transient and I don't want to keep it i the database. For example, I have currently two classes of users. Perhaps 1000 users enter data. I can store their data in the database even if it is temporary. But then I have those who want to view the data. And I have 50k page loads, which is not a huge amount, but I would prefer the components to store and process the transient data for these users in the frontend.
So to build a component hierarchy, and to start with a autocomplete, my approach could be something like:
Any thoughts?
Beta Was this translation helpful? Give feedback.
All reactions