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