I’m using Django with HTMX to manage a CRUD table in which I want to list and delete objects.
For this, I have a ListView which displays a table (using django-tables) with pagination, sorting, and text search features. It works as expected with HTMX: for example, if you go to the next page, the whole page is not reloaded: HTMX gets the table and upload a specific part of the DOM.
It looks like this:
The code of the ListView looks like:
class Proposals(SingleTableMixin, SearchableMixin, ListView):
table_class = ProposalTable # for django-tables2
ordering = "id"
model = Proposal
paginate_by = 5
search_filters = ["title__icontains"] # custom text search
def get_template_names(self):
# Trick to chose between loading the whole page (first time user goes to the page) or just the table via HTMX (when user uses pagination or sorting, it reloads the table only in the DOM)
if self.request.htmx:
return "fragments/proposals_fragment.html"
return "proposals.html"
Now, I’m trying to add a delete feature, with the best UX. I have explored multiple ways until now:
Just by removing the row from the DOM once the object is actually removed from the DB → bad: while it’s fast, it makes the pagination wrong/inconsistent, and with less objects in the table page.
Telling HTMX to redirect to the current url (response["HX-Redirect"] = request.htmx.current_url
) → bad: while the final result is ok, it’s slow, and the user can use the UI and make unwanted actions until the redirection has actually occurred. And of course, I don’t benefit from HTMX partial DOM update features here.
So, I was thinking of a 3rd method which sounds better:
The thing is I have no idea about how to do this in Django. I’m pretty sure I don't want to mess with FBVs, but I need some guidance. Here is the things I’m thinking of:
MultipleObjectTemplateResponseMixin
+ BaseListView
+ DeletionMixin
. Or maybe others?Am I on the right path? Can you provide some guidance, especially about how to make combined generic views, if it's a good idea to you?
Thanks a lot.
What you want to do is to implement delete
method on the Proposals
list view, DeleteMixin
implementation is very simple so you can use it and have something like this:
class Proposals(SingleTableMixin, SearchableMixin, DeletionMixin, ListView):
table_class = ProposalTable # for django-tables2
ordering = "id"
model = Proposal
paginate_by = 5
search_filters = ["title__icontains"] # custom text search
def get_template_names(self):
if self.request.htmx and not self.request.htmx.history_restore_request:
return "fragments/proposals_fragment.html"
return "proposals.html"
def delete(self, request, *args, **kwargs):
super().delete(request, *args, **kwargs)
return super().get(request, *args, **kwargs)
Here you override the delete, let it play and then return result as it was normal get instead of the redirect. And you want also want to handle htmx.history_restore_request
I added that as well.