Quickstart
The idea of hx-requests is that HXRequests
absorb all htmx requests.
Define an HXRequest
(we’ll get into how to do that in just a sec) and
observe the magic of hx-requests
.
No need to define extra urls to handle these requests
No need to add anything extra in views
Reusable
HXRequests
across viewsBuilt in
HXReuqests
to reduce boilerplate code (Forms, Deleting, Modals)
Making a GET Request (hx-get)
The View
The view requires HtmxViewMixin
from hx_requests.views import HtmxViewMixin
from django.views.generic.base import View
class MyView(HtmxViewMixin, View):
pass
The HTML
{% load hx_tags %}
<div id="user_info_target"></div>
<button {% hx_get 'get_user_info' %}
hx-target="#user_info_target"
type="button">
Click Me
</button>
- Notes:
Using the hx_get template tag signifies that it’s an
hx-get
‘get_user_info’ is the name of this
HXRequest
. See below to understand what that meansThe goal of this
hx-get
is to render a user info card into the empty div
Create the HXRequest
Create an hx_requests.py
file
Warning
All HXRequests
must be defined inside an hx_requests.py
file, and the hx_requests.py
files must live inside an app that’s included in Django’s INSTALLED_APPS
.
hx-get
will get directed to this HXRequest
.from hx_requests.hx_requests import BaseHXRequest
class GetUserInfo(BaseHXRequest):
name = "get_user_info"
GET_template = "user_info_card.html"
- Notes:
GetUserInfo
will return the HTML from theGET_template
(user_info_card.html
)
user_info_card.html
<div>
<p>Username:{{request.user.username}}</p>
<p>Email:{{request.user.email}}</p>
</div>
Summary
HXRequest
that matches the name (1st argument) passed into the hx_get
template tag. In this example ‘get_user_info’. That’s how the hx-get
is routed to GetUserInfo
.GET_template
.Note
The GET_template
has access to all of the context that is in the view.
Making a POST Request (hx-post)
Alomost exactly the same as the GET
request above.
Note
Working with a form? See Using Forms
The View
The view requires HtmxViewMixin
from hx_requests.views import HtmxViewMixin
from django.views.generic.base import View
class MyView(HtmxViewMixin, View):
pass
The HTML
{% load hx_tags %}
<div id="email_display">{{request.user.email}}</div>
<input type="text" name="email" id='email_input'/>
<button {% hx_post 'change_email' %}
hx-target="#email_display"
hx-include="#email_input"
type="button">
Save
</button>
- Notes:
Using the hx_post template tag signifies that it’s an
hx-post
The goal of this
hx-post
is to change the signed in user’s email to the value of the input replace the email address in the div with the updated email
Create the HXRequest
Create an hx_requests.py
file
Warning
All HXRequests
must be defined inside an hx_requests.py
file, and the hx_requests.py
files must live inside an app that’s included in Django’s INSTALLED_APPS
.
hx-post
will get directed to this HXRequest
.from hx_requests.hx_requests import BaseHXRequest
class ChangeEmail(BaseHXRequest):
name = "change_email"
POST_template = "email.html"
def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
user = request.user
user.email = request.POST.get("email")
user.save()
return super().post(request, *args, **kwargs)
- Notes:
ChangeEmail
will return the HTML from thePOST_template
(email.html
)
email.html
<span>{{request.user.email}}</span>
Summary
HXRequest
that matches the name (1st argument) passed into the hx_post
template tag. In this example ‘change_email’. That’s how the hx-post
is routed to ChangeEmail
.POST_template
.Note
The POST_template
has access to all of the context that is in the view.
Adding context to the templates
Many times you may need additional context in the GET_template
or POST_template
. Luckily, there is
a simple way to add context to them.
from hx_requests.hx_requests import BaseHXRequest
class MyHXRequest(BaseHXRequest):
...
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["important_var"] = "I am important"
return context
Additionally, if you only want the contex added on post (i.e. you want one of the form values in the POST_template
), you can
instead override get_post_context_data
from hx_requests.hx_requests import BaseHXRequest
class MyHXRequest(BaseHXRequest):
...
def get_post_context_data(self, **kwargs):
context = super().get_post_context_data(**kwargs)
context["important_var"] = "I am important"
return context
Note
The GET_template
and the POST_template
have access to hx_obect
(or the name it’s given by setting hx_object_name
)
and the kwargs passed into hx_get
or hx_post
.
For example:
{% hx_get 'my_hx_request' object=object my_awesome_kwarg="I am awesome" %}
In the GET_template
, ‘my_awesome_kwarg’ can be accessed as my_awesome_kwarg
unless kwargs_as_context
is set to False then it can be accessed as {{ hx_kwargs.my_awesome_kwarg }}
Context setup by get
One key feature of hx-requests
is that the HxRequest
class grants access to the context of the view it is associated with.
However, a common issue arises when the view sets up attributes within its get
method that the context relies on.
This poses a challenge because HXRequest
does not directly invoke the view’s get
method, potentially resulting in an error where
self.{var}
is inaccessible.
To mitigate this issue, hx-requests
automatically resolves Django’s views and invokes the get
method on your behalf.
Notably, it does so without returning the response immediately. This approach minimizes performance overhead,
as returning the response entails the view evaluating the entire response, which can be detrimental to performance.
Additionally, hx-requests
offers the flexibility to configure get
behavior for custom views through settings,
as detailed in the settings.
Example of the get for a UpdateView
:
def update_view_get(self, request, *args, **kwargs):
self.object = self.get_object()
- Notes:
UpdateView
relys on the get setting theself.object
attribute.hx-requests
will call theget
method and set theself.object
attribute for you.The function takes the same arguments as the
get
method of the view.
Example of setting up a custom view’s get:
def my_custom_view_get(self, request, *args, **kwargs):
self.my_custom_attribute = "I am custom"
# In settings.py
HX_REQUESTS_CUSTOM_VIEWS_SETUP = {
'my_app.views.my_custom_view' : 'my_app.view_get_functions.custom_view_get',
}
Note
A good example of a use case is if you are using django-filters. The FilterView
sets up attributes in the get
method
and also passes them to the context. To use FilterView
with hx-requests
, you would need to setup the get
method
to match the get
method of the FilterView
and return the extra context instead of the response.
def filter_view_get(self,request,*args,**kwargs):
filterset_class = self.get_filterset_class()
self.filterset = self.get_filterset(filterset_class)
if (
not self.filterset.is_bound
or self.filterset.is_valid()
or not self.get_strict()
):
self.object_list = self.filterset.qs
else:
self.object_list = self.filterset.queryset.none()
# Return the extra context
return {'filter': self.filterset, 'object_list': self.object_list}