From 3f93cebf41c38b8aa61c3a76c19b5e67fcf9770f Mon Sep 17 00:00:00 2001 From: Arona Jones Date: Mon, 8 Feb 2021 18:18:16 +0000 Subject: [PATCH] Much prefetch/select related optimisations --- RIGS/finance.py | 7 ++++--- RIGS/hs.py | 7 ++++--- RIGS/models.py | 14 +++++++++++--- RIGS/rigboard.py | 2 +- RIGS/templates/hs_object_list.html | 4 ++-- RIGS/templates/invoice_list.html | 2 +- RIGS/templates/invoice_list_waiting.html | 2 +- assets/views.py | 14 ++++++++------ 8 files changed, 32 insertions(+), 20 deletions(-) diff --git a/RIGS/finance.py b/RIGS/finance.py index 9486b8ee..0f6f8fbf 100644 --- a/RIGS/finance.py +++ b/RIGS/finance.py @@ -166,16 +166,17 @@ class InvoiceWaiting(generic.ListView): def get_context_data(self, **kwargs): context = super(InvoiceWaiting, self).get_context_data(**kwargs) total = 0 - for obj in self.get_objects(): + objects = self.get_queryset() + for obj in objects: total += obj.sum_total - context['page_title'] = "Events for Invoice ({} Events, £{:.2f})".format(len(self.get_objects()), total) + context['page_title'] = "Events for Invoice ({} Events, £{:.2f})".format(len(objects), total) return context def get_queryset(self): return self.get_objects() def get_objects(self): - # @todo find a way to select items + # TODO find a way to select items events = self.model.objects.filter( ( Q(start_date__lte=datetime.date.today(), end_date__isnull=True) | # Starts before with no end diff --git a/RIGS/hs.py b/RIGS/hs.py index 2669feab..e46c1d62 100644 --- a/RIGS/hs.py +++ b/RIGS/hs.py @@ -76,6 +76,9 @@ class EventRiskAssessmentList(generic.ListView): model = models.RiskAssessment template_name = 'hs_object_list.html' + def get_queryset(self): + return self.model.objects.order_by('reviewed_at').select_related('event') + def get_context_data(self, **kwargs): context = super(EventRiskAssessmentList, self).get_context_data(**kwargs) context['title'] = 'Risk Assessment' @@ -83,7 +86,6 @@ class EventRiskAssessmentList(generic.ListView): context['edit'] = 'ra_edit' context['review'] = 'ra_review' context['perm'] = 'perms.RIGS.review_riskassessment' - context['fields'] = [n.name for n in list(self.model._meta.get_fields()) if n.name != 'reviewed_at' and n.name != 'reviewed_by' and not n.is_relation and not n.auto_created] return context @@ -187,7 +189,6 @@ class EventChecklistList(generic.ListView): context['edit'] = 'ec_edit' context['review'] = 'ec_review' context['perm'] = 'perms.RIGS.review_eventchecklist' - context['fields'] = [n.name for n in list(self.model._meta.get_fields()) if n.name != 'reviewed_at' and n.name != 'reviewed_by' and not n.is_relation and not n.auto_created] return context @@ -209,7 +210,7 @@ class HSList(generic.ListView): template_name = 'hs_list.html' def get_queryset(self): - return models.Event.objects.all().order_by('-start_date') + return models.Event.objects.all().order_by('-start_date').select_related('riskassessment').prefetch_related('checklists') def get_context_data(self, **kwargs): context = super(HSList, self).get_context_data(**kwargs) diff --git a/RIGS/models.py b/RIGS/models.py index 4509143b..6c5f5582 100644 --- a/RIGS/models.py +++ b/RIGS/models.py @@ -52,7 +52,7 @@ class Profile(AbstractUser): @property def latest_events(self): - return self.event_mic.order_by('-start_date').select_related('person', 'organisation', 'venue', 'mic') + return self.event_mic.order_by('-start_date').select_related('person', 'organisation', 'venue', 'mic', 'riskassessment', 'invoice').prefetch_related('checklists') @classmethod def admins(cls): @@ -244,7 +244,7 @@ class EventManager(models.Manager): (models.Q(dry_hire=True, checked_in_by__isnull=True) & ( models.Q(status=Event.BOOKED) | models.Q(status=Event.CONFIRMED))) | # Active dry hire GT models.Q(status=Event.CANCELLED, start_date__gte=timezone.now()) # Canceled but not started - ).order_by('start_date', 'end_date', 'start_time', 'end_time', 'meet_at').select_related('person', 'organisation', 'venue', 'mic', 'riskassessment', 'invoice').prefetch_related('checklists') + ).order_by('start_date', 'end_date', 'start_time', 'end_time', 'meet_at').select_related('person', 'organisation', 'venue', 'mic') return events @@ -345,7 +345,7 @@ class Event(models.Model, RevisionMixin): @property def sum_total(self): - total = EventItem.objects.filter(event=self).aggregate( + total = self.items.aggregate( sum_total=models.Sum(models.F('cost') * models.F('quantity'), output_field=models.DecimalField(max_digits=10, decimal_places=2)) )['sum_total'] @@ -706,6 +706,10 @@ class RiskAssessment(models.Model, RevisionMixin): ('review_riskassessment', 'Can review Risk Assessments') ] + @cached_property + def fields(self): + return [n.name for n in list(self._meta.get_fields()) if n.name != 'reviewed_at' and n.name != 'reviewed_by' and not n.is_relation and not n.auto_created] + @property def event_size(self): # Confirm event size. Check all except generators, since generators entails outside @@ -788,6 +792,10 @@ class EventChecklist(models.Model, RevisionMixin): inverted_fields = [] + @cached_property + def fields(self): + return [n.name for n in list(self.model._meta.get_fields()) if n.name != 'reviewed_at' and n.name != 'reviewed_by' and not n.is_relation and not n.auto_created] + class Meta: ordering = ['event'] permissions = [ diff --git a/RIGS/rigboard.py b/RIGS/rigboard.py index 7e6cc388..45da678f 100644 --- a/RIGS/rigboard.py +++ b/RIGS/rigboard.py @@ -41,7 +41,7 @@ class RigboardIndex(generic.TemplateView): context = super(RigboardIndex, self).get_context_data(**kwargs) # call out method to get current events - context['events'] = models.Event.objects.current_events() + context['events'] = models.Event.objects.current_events().select_related('riskassessment', 'invoice').prefetch_related('checklists') context['page_title'] = "Rigboard" return context diff --git a/RIGS/templates/hs_object_list.html b/RIGS/templates/hs_object_list.html index 65a07daf..8849b168 100644 --- a/RIGS/templates/hs_object_list.html +++ b/RIGS/templates/hs_object_list.html @@ -21,7 +21,7 @@ Event {# mmm hax #} {% if object_list.0 != None %} - {% for field in fields %} + {% for field in object_list.0.fields %} {{ object_list.0|verbose_name:field|title }} {% endfor %} {% endif %} @@ -33,7 +33,7 @@ {# General #} {{ object.event }} - {% for field in fields %} + {% for field in object_list.0.fields %} {{ object|get_field:field }} {% endfor %} {# Buttons #} diff --git a/RIGS/templates/invoice_list.html b/RIGS/templates/invoice_list.html index c8648f09..70d84353 100644 --- a/RIGS/templates/invoice_list.html +++ b/RIGS/templates/invoice_list.html @@ -42,7 +42,7 @@ {{ invoice.event.start_date }} {{ invoice.invoice_date }} - {{ invoice.balance|floatformat:2 }} + £{{ invoice.balance|floatformat:2 }} {% if not invoice.event.internal %}
{{ invoice.event.purchase_order }} diff --git a/RIGS/templates/invoice_list_waiting.html b/RIGS/templates/invoice_list_waiting.html index cc19bd15..ee731d7b 100644 --- a/RIGS/templates/invoice_list_waiting.html +++ b/RIGS/templates/invoice_list_waiting.html @@ -53,7 +53,7 @@ {% endif %} - {{ event.sum_total|floatformat:2 }} + £{{ event.sum_total|floatformat:2 }}
{% if not event.internal %}{{ event.purchase_order }}{% endif %} diff --git a/assets/views.py b/assets/views.py index c00a37a1..c38ff368 100644 --- a/assets/views.py +++ b/assets/views.py @@ -39,12 +39,12 @@ 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().select_related('category', 'status') + queryset = self.model.objects.all() elif len(query_string) >= 3: queryset = self.model.objects.filter( - Q(asset_id__exact=query_string) | Q(description__icontains=query_string) | Q(serial_number__exact=query_string)).select_related('category', 'status') + Q(asset_id__exact=query_string) | Q(description__icontains=query_string) | Q(serial_number__exact=query_string)) else: - queryset = self.model.objects.filter(Q(asset_id__exact=query_string)).select_related('category', 'status') + queryset = self.model.objects.filter(Q(asset_id__exact=query_string)) if form.cleaned_data['category']: queryset = queryset.filter(category__in=form.cleaned_data['category']) @@ -55,7 +55,7 @@ class AssetList(LoginRequiredMixin, generic.ListView): queryset = queryset.filter( status__in=models.AssetStatus.objects.filter(should_show=True)) - return queryset + return queryset.select_related('category', 'status') def get_context_data(self, **kwargs): context = super(AssetList, self).get_context_data(**kwargs) @@ -180,7 +180,7 @@ class AssetAuditList(AssetList): # TODO Refresh this when the modal is submitted def get_queryset(self): self.form = forms.AssetSearchForm(data=self.request.GET) - return self.model.objects.filter(Q(last_audited_at__isnull=True)) + return self.model.objects.filter(Q(last_audited_at__isnull=True)).select_related('category', 'status') def get_context_data(self, **kwargs): context = super(AssetAuditList, self).get_context_data(**kwargs) @@ -288,7 +288,9 @@ class CableTypeList(generic.ListView): model = models.CableType template_name = 'cable_type_list.html' paginate_by = 40 - # ordering = ['__str__'] + + def get_queryset(self): + return self.model.objects.select_related('plug', 'socket') def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs)