Refactor search logic to a create an 'omnisearch' (#484)

This commit is contained in:
2022-02-08 15:01:01 +00:00
committed by GitHub
parent 3e1e0079d8
commit 54c90a7be4
19 changed files with 290 additions and 164 deletions

View File

@@ -2,11 +2,12 @@ import re
from django.core.exceptions import ValidationError
from django.db import models, connection
from django.db.models import Q
from django.urls import reverse
from reversion import revisions as reversion
from reversion.models import Version
from RIGS.models import Profile
from RIGS.models import Profile, ContactableManager
from versioning.versioning import RevisionMixin
@@ -46,6 +47,8 @@ class Supplier(models.Model, RevisionMixin):
notes = models.TextField(blank=True, default="")
objects = ContactableManager()
class Meta:
ordering = ['name']
@@ -107,6 +110,15 @@ def get_available_asset_id(wanted_prefix=""):
cursor.close()
class AssetManager(models.Manager):
def search(self, query=None):
qs = self.get_queryset()
if query is not None:
or_lookup = (Q(asset_id__exact=query.upper()) | Q(description__icontains=query) | Q(serial_number__exact=query))
qs = qs.filter(or_lookup).distinct() # distinct() is often necessary with Q lookups
return qs
@reversion.register
class Asset(models.Model, RevisionMixin):
parent = models.ForeignKey(to='self', related_name='asset_parent',
@@ -142,6 +154,8 @@ class Asset(models.Model, RevisionMixin):
reversion_perm = 'assets.asset_finance'
objects = AssetManager()
class Meta:
ordering = ['asset_id_prefix', 'asset_id_number']
permissions = [

View File

@@ -75,13 +75,13 @@
<div class="col">
<div id="category-group" class="form-group px-1" style="margin-bottom: 0;">
<label for="category" class="sr-only">Category</label>
{% render_field form.category|attr:'multiple'|add_class:'form-control custom-select selectpicker col-sm' data-none-selected-text="Categories" data-header="Categories" data-actions-box="true" %}
{% render_field form.category|attr:'multiple'|add_class:'selectpicker col-sm' data-none-selected-text="Categories" data-header="Categories" data-actions-box="true" %}
</div>
</div>
<div class="col">
<div id="status-group" class="form-group px-1" style="margin-bottom: 0;">
<label for="status" class="sr-only">Status</label>
{% render_field form.status|attr:'multiple'|add_class:'form-control custom-select selectpicker col-sm' data-none-selected-text="Statuses" data-header="Statuses" data-actions-box="true" %}
{% render_field form.status|attr:'multiple'|add_class:'selectpicker col-sm' data-none-selected-text="Statuses" data-header="Statuses" data-actions-box="true" %}
</div>
</div>
<div class="col mt-2">

View File

@@ -20,7 +20,7 @@ urlpatterns = [
path('asset/id/<asset:pk>/duplicate/', permission_required_with_403('assets.add_asset')
(views.AssetDuplicate.as_view()), name='asset_duplicate'),
path('asset/id/<asset:pk>/label', login_required(views.GenerateLabel.as_view()), name='generate_label'),
path('asset/<list:ids>/list/label', views.GenerateLabels.as_view(), name='generate_labels'),
path('asset/<list:ids>/list/label', views.GenerateLabels.as_view(), name='generate_labels'),
path('cabletype/list/', login_required(views.CableTypeList.as_view()), name='cable_type_list'),
path('cabletype/create/', permission_required_with_403('assets.add_cable_type')(views.CableTypeCreate.as_view()), name='cable_type_create'),

View File

@@ -50,13 +50,7 @@ class AssetList(LoginRequiredMixin, generic.ListView):
# TODO Feedback to user when search fails
query_string = form.cleaned_data['q'] or ""
if len(query_string) == 0:
queryset = self.model.objects.all()
elif len(query_string) >= 3:
queryset = self.model.objects.filter(
Q(asset_id__exact=query_string.upper()) | Q(description__icontains=query_string) | Q(serial_number__exact=query_string))
else:
queryset = self.model.objects.filter(Q(asset_id__exact=query_string.upper()))
queryset = models.Asset.objects.search(query=query_string)
if form.cleaned_data['is_cable']:
queryset = queryset.filter(is_cable=True)
@@ -176,6 +170,7 @@ class AssetOEmbed(OEmbedView):
class AssetAuditList(AssetList):
template_name = 'asset_audit_list.html'
hide_hidden_status = True
# TODO Refresh this when the modal is submitted
def get_queryset(self):
@@ -388,12 +383,14 @@ class GenerateLabels(generic.View):
base64_encoded_result_str = base64_encoded_result_bytes.decode('ascii')
images.append(base64_encoded_result_str)
name = f"Asset Label Sheet generated at {timezone.now()}"
context = {
'images0': images[::4],
'images1': images[1::4],
'images2': images[2::4],
'images3': images[3::4],
'filename': "Asset Label Sheet generated at {}".format(timezone.now())
'filename': name
}
merger = PdfFileMerger()
@@ -405,6 +402,6 @@ class GenerateLabels(generic.View):
merged = BytesIO()
merger.write(merged)
response['Content-Disposition'] = 'filename="{}"'.format(context['filename'])
response['Content-Disposition'] = f'filename="{name}"'
response.write(merged.getvalue())
return response