red-france-69804
08/05/2022, 10:39 AMpython
class DeleteListView(SingleObjectMixin, ListView):
def delete(self, request, *args, **kwargs):
"""Add delete logic (without redirection) to ListView get method"""
self.object = self.get_object()
self.object.delete()
return super().get(self, request, *args, **kwargs)
red-france-69804
08/05/2022, 10:43 AMjolly-kite-167
08/06/2022, 1:46 AMincalculable-holiday-29658
08/06/2022, 7:24 AMblue-ghost-19146
08/06/2022, 7:46 AMblue-ghost-19146
08/06/2022, 7:53 AMDeleteView
etc, but instead have get
, put
, delete
methods within one class. I definitely prefer Method 2 for simplicity, but I do agree that method 1 may have better atomicity.
What do you mean by βhaving to deal with the UI between 2 requestsβ for method 2? I understand that there are 2 requests, the delete then the subsequent list update, but what challenges does that pose to the UI in between? It should be as simple as the delete view deleting the item from the DB, then the list view updating the list with the latest data, right?red-france-69804
08/07/2022, 3:53 PMpython
class RefreshTableMixin:
"""Fire an HX-Trigger event to be handled client side, to indicate that a table need to be refreshed.
"""
def build_response(self, request, *args, **kwargs):
response = super().build_response(self, request, *args, **kwargs)
trigger_client_event(response, name=REFRESH_TABLE_EVENT, params=None)
return response
class EmptyResponse:
def build_response(self, request, *args, **kwargs):
return HttpResponse("")
class HTMXDeleteView(RefreshTableMixin, EmptyResponse, DeleteView):
"""Delete View with empty response and no redirection
Add a custom event to be used client-side with HTMX.
"""
def delete(self, request, *args, **kwargs):
self.object = self.get_object()
self.object.delete()
response = self.build_response(request)
return response
red-france-69804
08/07/2022, 3:58 PMhtml
<button
...
_="on refreshTableEvent remove .modal-open from #{@data-modal-content}"
data-modal-content="modal-delete-{{record.pk}}-content"
>
Delete
</button>
bitter-monkey-50309
08/07/2022, 5:21 PMonclick
event on the button in the modal to disable it and then event handlers for HTMX errors to display a toast with a generic failure message and re-enable the button for the user to try again.red-france-69804
08/07/2022, 9:34 PM<div>
in the DOM, as the events are received.red-france-69804
08/07/2022, 9:34 PMpython
import secrets
from django_htmx.http import trigger_client_event
class MessageMixin:
"""Provide a way to add a formatable message (like toast) to a class based view, using attributes. Kwargs can be added to format message with dynamic data.
An HX-Trigger event is fired to be handled client-side.
"""
message: str | None = None
message_level: str | None = None
message_kwargs: dict = {}
def build_response(self, request, *args, **kwargs):
response = super().build_response(self, request, *args, **kwargs)
trigger_client_event(
response,
name="showMessage",
params=dict(
level=self.message_level,
message=self.message.format(**self.message_kwargs),
randomId=secrets.token_urlsafe(nbytes=5), # allow to handle multiple toasts concurrenly
),
)
return response
toaster.html
html
{# Toast template used to create actual toasts with render hyperscript method #}
<template id="toast-template">
<div
id="toast-${randomId}"
class="alert alert-${level} shadow-lg mb-3"
_="init
wait 2s
transition my opacity to 0
remove me"
>
<span>${message}</span>
<button
_="on click remove #toast-${randomId}"
class="btn btn-xs btn-circle">
β
</button>
</template>
{# Toaster (toasts wrapper) #}
<div
class="z-20 fixed bottom-4 right-8 ml-8"
_="on showMessage(message,level,randomId) from body
render #toast-template with (message: message, level: level, randomId: randomId)
then put it at the end of me"
>
</div>
red-france-69804
08/07/2022, 9:37 PMhttps://im5.ezgif.com/tmp/ezgif-5-137cb37675.gifβΎ
white-motorcycle-95262
08/10/2022, 4:20 PMhx-target
of the request?red-france-69804
08/11/2022, 12:04 PMHX-Redirect
attribute, to trigger the redirection from the client, using HTMX.
I can't help more as I have no example usage in mind right now.
python
class HttpResponseClientRedirect(HttpResponseRedirectBase):
status_code = 200
def __init__(self, redirect_to: str, *args: Any, **kwargs: Any) -> None:
super().__init__(redirect_to, *args, **kwargs)
self["HX-Redirect"] = self["Location"]
del self["Location"]
red-france-69804
08/11/2022, 3:03 PMdjango
<input
id="search-field"
type="search"
name="search" {# this creates the 'search' GET query paramater #}
hx-get="{% querystring %}" {# current URL with existing query parameters - search param will be added automatically #}
hx-trigger="keyup changed delay:500ms, search"
hx-target="#table-container"
hx-swap="outerHTML"
hx-push-url="true"
>
The querystring
template tag you see comes from django-tables (https://github.com/jieter/django-tables2/blob/master/django_tables2/templatetags/django_tables2.py) and as explained in the source code, it allows to build a relative url, keeping already existing query parameters. This is exactly what I need when running a search, as I want to keep other query parameters (like sorting).
I'll describe my issue with an example:β¨
If I go directly to "http://localhost:8000/objects?sort=title", I can see that the value of hx-get is hx-get="?sort=title"
, as expected. Which means if I run a search, the final search url suffix will be something like ?sort=title&search=foo
(as expected).
β¨β¨ However, if I go to http://localhost:8000/objects and then use a button on my UI to trigger an HTMX query that updates the URL to "http://localhost:8000/objects?sort=title", the value of hx-get is still empty (hx-get="?"
).β¨
Then, of course if I run a search, the final search url suffix misses the sorting.
β¨β¨ All of this is obvious because the <input>
part is NEVER updated by htmx. Hence the {% querystring %}
tag has is evaluated once when loading the http://localhost:8000/objects
page, and can't change after that.
While I understand where my problem comes from, I'm not sure how to deal with this properly. Maybe include the <input>
into the HTMX response (but feel unnatural)?
Thanks for your help.delightful-student-39557
08/15/2022, 8:33 AMcalm-queen-64495
08/15/2022, 1:21 PMcalm-queen-64495
08/15/2022, 1:23 PMclass RoleUpdateView(UpdateView):
model = Role
form_class = RoleForm
template_name = "partials/role-form.html"
def post(self, request, pk):
return super().post(request)
early-camera-41285
08/15/2022, 2:49 PMHX-Trigger
header on the response object?calm-queen-64495
08/16/2022, 12:26 AMcalm-queen-64495
08/16/2022, 6:37 AMcalm-queen-64495
08/16/2022, 6:38 AMcalm-queen-64495
08/16/2022, 7:42 AMcalm-queen-64495
08/16/2022, 7:48 AMcalm-queen-64495
08/16/2022, 7:48 AMearly-camera-41285
08/16/2022, 11:56 AMpython
def my_view(request):
response = HttpResponse(status=204)
response['HX-Trigger'] = 'myCustomEvent'
return response
def html_response(request):
response = render(request, 'my_templage.html', {'context': ''})
response['HX-Trigger'] = 'myCustomEvent'
return response
calm-queen-64495
08/17/2022, 3:58 AM_="on click
call Swal.fire({title: 'Confirm', text:'Do you want to continue?'})
if result.isConfirmed trigger confirmed">
But the Modal closes along with the sweetalert, so the confirmed is not fired.
How would you stop the modal from closing, so the use can choose to confirm or deny the request?mysterious-toddler-20573
08/17/2022, 4:07 PMmysterious-toddler-20573
08/17/2022, 4:07 PMmysterious-toddler-20573
08/17/2022, 4:07 PM