mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-24 16:26:09 -06:00
Clean up search view form
This commit is contained in:
parent
e66902c05c
commit
bcc5f6c504
@ -1,7 +1,7 @@
|
||||
from django import forms
|
||||
|
||||
from netbox.search.backends import search_backend
|
||||
from utilities.forms import BootstrapMixin
|
||||
from utilities.forms import BootstrapMixin, StaticSelectMultiple
|
||||
|
||||
from .base import *
|
||||
|
||||
@ -21,18 +21,21 @@ def build_options(choices):
|
||||
|
||||
class SearchForm(BootstrapMixin, forms.Form):
|
||||
q = forms.CharField(label='Search')
|
||||
obj_types = forms.MultipleChoiceField(
|
||||
choices=[],
|
||||
required=False,
|
||||
label='Object type(s)',
|
||||
widget=StaticSelectMultiple()
|
||||
)
|
||||
options = None
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields["obj_type"] = forms.ChoiceField(
|
||||
choices=search_backend.get_search_choices(),
|
||||
required=False,
|
||||
label='Type'
|
||||
)
|
||||
|
||||
self.fields['obj_types'].choices = search_backend.get_object_types()
|
||||
|
||||
def get_options(self):
|
||||
if not self.options:
|
||||
self.options = build_options(search_backend.get_search_choices())
|
||||
self.options = build_options(search_backend.get_object_types())
|
||||
|
||||
return self.options
|
||||
|
@ -12,6 +12,7 @@ from extras.models import CachedValue
|
||||
from extras.registry import registry
|
||||
from netbox.constants import SEARCH_MAX_RESULTS
|
||||
from utilities.querysets import RestrictedPrefetch
|
||||
from utilities.templatetags.builtins.filters import bettertitle
|
||||
from . import FieldTypes, LookupTypes, SearchResult, get_registry
|
||||
|
||||
# The cache for the initialized backend.
|
||||
@ -42,7 +43,7 @@ class SearchBackend:
|
||||
post_save.connect(self.caching_handler)
|
||||
post_delete.connect(self.removal_handler)
|
||||
|
||||
def get_search_choices(self):
|
||||
def get_object_types(self):
|
||||
"""Return the set of choices for individual object types, organized by category."""
|
||||
if not self._search_choice_options:
|
||||
|
||||
@ -50,7 +51,7 @@ class SearchBackend:
|
||||
categories = defaultdict(dict)
|
||||
for app_label, models in registry['search'].items():
|
||||
for name, cls in models.items():
|
||||
title = cls.model._meta.verbose_name.title()
|
||||
title = bettertitle(cls.model._meta.verbose_name)
|
||||
value = f'{app_label}.{name}'
|
||||
categories[cls.get_category()][value] = title
|
||||
|
||||
|
@ -150,18 +150,18 @@ class HomeView(View):
|
||||
class SearchView(View):
|
||||
|
||||
def get(self, request):
|
||||
form = SearchForm(request.GET)
|
||||
object_types = None
|
||||
results = []
|
||||
|
||||
# Initialize search form
|
||||
form = SearchForm(request.GET) if 'q' in request.GET else SearchForm()
|
||||
|
||||
if form.is_valid():
|
||||
|
||||
# Restrict results by object type
|
||||
if form.cleaned_data['obj_type']:
|
||||
app_label, model_name = form.cleaned_data['obj_type'].split('.')
|
||||
object_types = [
|
||||
ContentType.objects.get_by_natural_key(app_label, model_name)
|
||||
]
|
||||
object_types = []
|
||||
for obj_type in form.cleaned_data['obj_types']:
|
||||
app_label, model_name = obj_type.split('.')
|
||||
object_types.append(ContentType.objects.get_by_natural_key(app_label, model_name))
|
||||
|
||||
results = search_backend.search(request, form.cleaned_data['q'], object_types=object_types)
|
||||
|
||||
|
@ -16,10 +16,21 @@
|
||||
{% endblock tabs %}
|
||||
|
||||
{% block content-wrapper %}
|
||||
<div class="tab-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>
|
||||
{% if request.GET.q %}
|
||||
{% if results %}
|
||||
<div class="row">
|
||||
<div class="row px-3">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-body table-responsive">
|
||||
@ -32,7 +43,7 @@
|
||||
</tr>
|
||||
{% for result in results %}
|
||||
<tr>
|
||||
<td>{{ result.object|content_type }}</td>
|
||||
<td>{{ result.object|meta:"verbose_name"|bettertitle }}</td>
|
||||
<td>
|
||||
<a href="{{ result.object.get_absolute_url }}">{{ result.object }}</a>
|
||||
</td>
|
||||
@ -48,26 +59,5 @@
|
||||
{% else %}
|
||||
<h3 class="text-muted text-center">No results found</h3>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<div class="row">
|
||||
<div class="col col-12 col-lg-6 offset-lg-3">
|
||||
<form action="{% url 'search' %}" method="get" class="form form-horizontal">
|
||||
<div class="card">
|
||||
<h5 class="card-header">
|
||||
Search
|
||||
</h5>
|
||||
<div class="card-body">
|
||||
{% render_form form %}
|
||||
</div>
|
||||
<div class="card-footer text-end">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<span class="mdi mdi-magnify" aria-hidden="true"></span> Search
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock content-wrapper %}
|
||||
|
@ -5,10 +5,9 @@
|
||||
aria-label="Search"
|
||||
placeholder="Search"
|
||||
class="form-control"
|
||||
value="{{ request.GET.q|escape }}"
|
||||
/>
|
||||
|
||||
<input name="obj_type" hidden type="text" class="search-obj-type" />
|
||||
<input name="obj_types" hidden type="text" class="search-obj-type" />
|
||||
|
||||
<span class="input-group-text search-obj-selected">All Objects</span>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user