Introduce SearchTable and enable HTMX for results

This commit is contained in:
jeremystretch 2022-10-18 08:49:08 -04:00
parent f69a13e05b
commit 7cc85a609d
5 changed files with 56 additions and 49 deletions

View File

@ -17,7 +17,14 @@ LOOKUP_CHOICES = (
class SearchForm(BootstrapMixin, forms.Form):
q = forms.CharField(
label='Search'
label='Search',
widget=forms.TextInput(
attrs={
'hx-get': '',
'hx-target': '#search_results',
'hx-trigger': 'keyup[target.value.length >= 3] changed delay:500ms',
}
)
)
obj_types = forms.MultipleChoiceField(
choices=[],

View File

@ -192,7 +192,7 @@ class CachedValueSearchBackend(SearchBackend):
# Wrap the base query to return only the lowest-weight result for each object
# Hat-tip to https://blog.oyam.dev/django-filter-by-window-function/ for the solution
sql, params = queryset.query.sql_with_params()
results = CachedValue.objects.prefetch_related(prefetch).raw(
results = CachedValue.objects.prefetch_related(prefetch, 'object_type').raw(
f"SELECT * FROM ({sql}) t WHERE row_number = 1",
params
)

View File

@ -4,6 +4,7 @@ from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import FieldDoesNotExist
from django.db.models.fields.related import RelatedField
from django.utils.translation import gettext as _
from django_tables2.data import TableQuerysetData
from extras.models import CustomField, CustomLink
@ -14,6 +15,7 @@ from utilities.paginator import EnhancedPaginator, get_paginate_count
__all__ = (
'BaseTable',
'NetBoxTable',
'SearchTable',
)
@ -192,3 +194,18 @@ class NetBoxTable(BaseTable):
])
super().__init__(*args, extra_columns=extra_columns, **kwargs)
class SearchTable(tables.Table):
object_type = columns.ContentTypeColumn()
object = tables.Column(
linkify=True
)
field = tables.Column()
value = tables.Column()
class Meta:
attrs = {
'class': 'table table-hover object-list',
}
empty_text = _('No results found')

View File

@ -8,7 +8,6 @@ from django.http import HttpResponseServerError
from django.shortcuts import redirect, render
from django.template import loader
from django.template.exceptions import TemplateDoesNotExist
from django.urls import reverse
from django.views.decorators.csrf import requires_csrf_token
from django.views.defaults import ERROR_500_TEMPLATE_NAME, page_not_found
from django.views.generic import View
@ -23,9 +22,10 @@ from extras.models import ObjectChange
from extras.tables import ObjectChangeTable
from ipam.models import Aggregate, IPAddress, IPRange, Prefix, VLAN, VRF
from netbox.forms import SearchForm
from netbox.search import get_registry
from netbox.search.backends import search_backend
from netbox.tables import SearchTable
from tenancy.models import Tenant
from utilities.htmx import is_htmx
from virtualization.models import Cluster, VirtualMachine
from wireless.models import WirelessLAN, WirelessLink
@ -170,9 +170,17 @@ class SearchView(View):
lookup=form.cleaned_data['lookup']
)
table = SearchTable(results)
# If this is an HTMX request, return only the rendered table HTML
if is_htmx(request):
return render(request, 'htmx/table.html', {
'table': table,
})
return render(request, 'search.html', {
'form': form,
'results': results,
'table': table,
})

View File

@ -15,49 +15,24 @@
</ul>
{% endblock tabs %}
{% block content-wrapper %}
<div class="row px-3">
<div class="col col-6 offset-3 py-3">
<form action="{% url 'search' %}" method="get" class="form form-horizontal">
{% render_form form %}
<div class="text-end">
<button type="submit" class="btn btn-primary">
<span class="mdi mdi-magnify" aria-hidden="true"></span> Search
</button>
</div>
</form>
{% block content %}
<div class="row px-3">
<div class="col col-6 offset-3 py-3">
<form action="{% url 'search' %}" method="get" class="form form-horizontal">
{% render_form form %}
<div class="text-end">
<button type="submit" class="btn btn-primary">
<span class="mdi mdi-magnify" aria-hidden="true"></span> Search
</button>
</div>
</form>
</div>
</div>
<div class="row px-3">
<div class="card">
<div class="card-body" id="search_results">
{% include 'htmx/table.html' %}
</div>
</div>
{% if request.GET.q %}
{% if results %}
<div class="row px-3">
<div class="col">
<div class="card">
<div class="card-body table-responsive">
<table class="table table-hover">
<tr>
<th>Type</th>
<th>Object</th>
<th>Field</th>
<th>Value</th>
</tr>
{% for result in results %}
<tr>
<td>{{ result.object|meta:"verbose_name"|bettertitle }}</td>
<td>
<a href="{{ result.object.get_absolute_url }}">{{ result.object }}</a>
</td>
<td>{{ result.field|placeholder }}</td>
<td>{{ result.value|placeholder }}</td>
</tr>
{% endfor %}
</table>
</div>
</div>
</div>
</div>
{% else %}
<h3 class="text-muted text-center">No results found</h3>
{% endif %}
{% endif %}
{% endblock content-wrapper %}
</div>
{% endblock content %}