Skip to content

Commit

Permalink
Closes #14735: Implement django-htmx (#14873)
Browse files Browse the repository at this point in the history
* Install django-htmx

* Replace is_htmx() function with request.htmx

* Remove is_embedded() HTMX utility

* Include django-htmx debug error handler
  • Loading branch information
jeremystretch authored Jan 22, 2024
1 parent da085e6 commit 1d41a8a
Show file tree
Hide file tree
Showing 9 changed files with 22 additions and 43 deletions.
4 changes: 4 additions & 0 deletions base_requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ django-filter
# https://github.com/flavors/django-graphiql-debug-toolbar/blob/main/CHANGES.rst
django-graphiql-debug-toolbar

# HTMX utilities for Django
# https://django-htmx.readthedocs.io/en/latest/changelog.html
django-htmx

# Modified Preorder Tree Traversal (recursive nesting of objects)
# Pinned to 0.14.0; 0.15.0 requires Python 3.9+
# https://github.com/django-mptt/django-mptt/blob/main/CHANGELOG.rst
Expand Down
13 changes: 5 additions & 8 deletions netbox/extras/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from django.apps import apps
from django.conf import settings
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.contenttypes.models import ContentType
Expand All @@ -20,7 +18,6 @@
from netbox.constants import DEFAULT_ACTION_PERMISSIONS
from netbox.views import generic
from utilities.forms import ConfirmationForm, get_field_value
from utilities.htmx import is_htmx
from utilities.paginator import EnhancedPaginator, get_paginate_count
from utilities.rqworker import get_workers_for_queue
from utilities.templatetags.builtins.filters import render_markdown
Expand Down Expand Up @@ -892,7 +889,7 @@ class DashboardWidgetAddView(LoginRequiredMixin, View):
template_name = 'extras/dashboard/widget_add.html'

def get(self, request):
if not is_htmx(request):
if not request.htmx:
return redirect('home')

initial = request.GET or {
Expand Down Expand Up @@ -942,7 +939,7 @@ class DashboardWidgetConfigView(LoginRequiredMixin, View):
template_name = 'extras/dashboard/widget_config.html'

def get(self, request, id):
if not is_htmx(request):
if not request.htmx:
return redirect('home')

widget = request.user.dashboard.get_widget(id)
Expand Down Expand Up @@ -983,7 +980,7 @@ class DashboardWidgetDeleteView(LoginRequiredMixin, View):
template_name = 'generic/object_delete.html'

def get(self, request, id):
if not is_htmx(request):
if not request.htmx:
return redirect('home')

widget = request.user.dashboard.get_widget(id)
Expand Down Expand Up @@ -1173,7 +1170,7 @@ def get(self, request, job_pk):
report = module.reports[job.name]

# If this is an HTMX request, return only the result HTML
if is_htmx(request):
if request.htmx:
response = render(request, 'extras/htmx/report_result.html', {
'report': report,
'job': job,
Expand Down Expand Up @@ -1347,7 +1344,7 @@ def get(self, request, job_pk):
script = module.scripts[job.name]()

# If this is an HTMX request, return only the result HTML
if is_htmx(request):
if request.htmx:
response = render(request, 'extras/htmx/script_result.html', {
'script': script,
'job': job,
Expand Down
2 changes: 2 additions & 0 deletions netbox/netbox/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ def _setting(name, default=None):
'debug_toolbar',
'graphiql_debug_toolbar',
'django_filters',
'django_htmx',
'django_tables2',
'django_prometheus',
'graphene_django',
Expand Down Expand Up @@ -405,6 +406,7 @@ def _setting(name, default=None):
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
'django_htmx.middleware.HtmxMiddleware',
'netbox.middleware.RemoteUserMiddleware',
'netbox.middleware.CoreMiddleware',
'netbox.middleware.MaintenanceModeMiddleware',
Expand Down
5 changes: 2 additions & 3 deletions netbox/netbox/views/generic/bulk_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
from utilities.exceptions import AbortRequest, AbortTransaction, PermissionsViolation
from utilities.forms import BulkRenameForm, ConfirmationForm, restrict_form_fields
from utilities.forms.bulk_import import BulkImportForm
from utilities.htmx import is_embedded, is_htmx
from utilities.permissions import get_permission_for_model
from utilities.utils import get_viewname
from utilities.views import GetReturnURLMixin
Expand Down Expand Up @@ -162,8 +161,8 @@ def get(self, request):
table = self.get_table(self.queryset, request, has_bulk_actions)

# If this is an HTMX request, return only the rendered table HTML
if is_htmx(request):
if is_embedded(request):
if request.htmx:
if request.htmx.target != 'object_list':
table.embedded = True
# Hide selection checkboxes
if 'pk' in table.base_columns:
Expand Down
11 changes: 5 additions & 6 deletions netbox/netbox/views/generic/object_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
from utilities.error_handlers import handle_protectederror
from utilities.exceptions import AbortRequest, PermissionsViolation
from utilities.forms import ConfirmationForm, restrict_form_fields
from utilities.htmx import is_htmx
from utilities.permissions import get_permission_for_model
from utilities.utils import get_viewname, normalize_querydict, prepare_cloned_fields
from utilities.views import GetReturnURLMixin
Expand Down Expand Up @@ -136,7 +135,7 @@ def get(self, request, *args, **kwargs):
table = self.get_table(table_data, request, has_bulk_actions)

# If this is an HTMX request, return only the rendered table HTML
if is_htmx(request):
if request.htmx:
return render(request, 'htmx/table.html', {
'object': instance,
'table': table,
Expand Down Expand Up @@ -224,7 +223,7 @@ def get(self, request, *args, **kwargs):
restrict_form_fields(form, request.user)

# If this is an HTMX request, return only the rendered form HTML
if is_htmx(request):
if request.htmx:
return render(request, 'htmx/form.html', {
'form': form,
})
Expand Down Expand Up @@ -349,7 +348,7 @@ def _handle_protected_objects(self, obj, protected_objects, request, exc):
"""
handle_protectederror(protected_objects, request, exc)

if is_htmx(request):
if request.htmx:
return HttpResponse(headers={
'HX-Redirect': obj.get_absolute_url(),
})
Expand Down Expand Up @@ -378,7 +377,7 @@ def get(self, request, *args, **kwargs):
return self._handle_protected_objects(obj, e.restricted_objects, request, e)

# If this is an HTMX request, return only the rendered deletion form as modal content
if is_htmx(request):
if request.htmx:
viewname = get_viewname(self.queryset.model, action='delete')
form_url = reverse(viewname, kwargs={'pk': obj.pk})
return render(request, 'htmx/delete_form.html', {
Expand Down Expand Up @@ -480,7 +479,7 @@ def get(self, request):
instance = self.alter_object(self.queryset.model(), request)

# If this is an HTMX request, return only the rendered form HTML
if is_htmx(request):
if request.htmx:
return render(request, 'htmx/form.html', {
'form': form,
})
Expand Down
3 changes: 1 addition & 2 deletions netbox/netbox/views/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
from netbox.search import LookupTypes
from netbox.search.backends import search_backend
from netbox.tables import SearchTable
from utilities.htmx import is_htmx
from utilities.paginator import EnhancedPaginator, get_paginate_count

__all__ = (
Expand Down Expand Up @@ -96,7 +95,7 @@ def get(self, request):
}).configure(table)

# If this is an HTMX request, return only the rendered table HTML
if is_htmx(request):
if request.htmx:
return render(request, 'htmx/table.html', {
'table': table,
})
Expand Down
2 changes: 2 additions & 0 deletions netbox/templates/base/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
{% load static %}
{% load helpers %}
{% load i18n %}
{% load django_htmx %}
<!DOCTYPE html>
<html
lang="en"
Expand Down Expand Up @@ -48,6 +49,7 @@
src="{% static 'netbox.js' %}?v={{ settings.VERSION }}"
onerror="window.location='{% url 'media_failure' %}?filename=netbox.js'">
</script>
{% django_htmx_script %}

{# Additional <head> content #}
{% block head %}{% endblock %}
Expand Down
24 changes: 0 additions & 24 deletions netbox/utilities/htmx.py

This file was deleted.

1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ django-cors-headers==4.3.1
django-debug-toolbar==4.2.0
django-filter==23.5
django-graphiql-debug-toolbar==0.2.0
django-htmx==1.17.2
django-mptt==0.14.0
django-pglocks==1.0.4
django-prometheus==2.3.1
Expand Down

0 comments on commit 1d41a8a

Please sign in to comment.