mirror of
https://github.com/nottinghamtec/PyRIGS.git
synced 2026-01-24 08:52:15 +00:00
Refactor search logic to a create an 'omnisearch' (#484)
This commit is contained in:
@@ -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 = [
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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'),
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user