Much prefetch/select related optimisations

This commit is contained in:
2021-02-08 18:18:16 +00:00
parent 603e919ad0
commit 3f93cebf41
8 changed files with 32 additions and 20 deletions

View File

@@ -166,16 +166,17 @@ class InvoiceWaiting(generic.ListView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(InvoiceWaiting, self).get_context_data(**kwargs) context = super(InvoiceWaiting, self).get_context_data(**kwargs)
total = 0 total = 0
for obj in self.get_objects(): objects = self.get_queryset()
for obj in objects:
total += obj.sum_total 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 return context
def get_queryset(self): def get_queryset(self):
return self.get_objects() return self.get_objects()
def get_objects(self): def get_objects(self):
# @todo find a way to select items # TODO find a way to select items
events = self.model.objects.filter( events = self.model.objects.filter(
( (
Q(start_date__lte=datetime.date.today(), end_date__isnull=True) | # Starts before with no end Q(start_date__lte=datetime.date.today(), end_date__isnull=True) | # Starts before with no end

View File

@@ -76,6 +76,9 @@ class EventRiskAssessmentList(generic.ListView):
model = models.RiskAssessment model = models.RiskAssessment
template_name = 'hs_object_list.html' 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): def get_context_data(self, **kwargs):
context = super(EventRiskAssessmentList, self).get_context_data(**kwargs) context = super(EventRiskAssessmentList, self).get_context_data(**kwargs)
context['title'] = 'Risk Assessment' context['title'] = 'Risk Assessment'
@@ -83,7 +86,6 @@ class EventRiskAssessmentList(generic.ListView):
context['edit'] = 'ra_edit' context['edit'] = 'ra_edit'
context['review'] = 'ra_review' context['review'] = 'ra_review'
context['perm'] = 'perms.RIGS.review_riskassessment' 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 return context
@@ -187,7 +189,6 @@ class EventChecklistList(generic.ListView):
context['edit'] = 'ec_edit' context['edit'] = 'ec_edit'
context['review'] = 'ec_review' context['review'] = 'ec_review'
context['perm'] = 'perms.RIGS.review_eventchecklist' 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 return context
@@ -209,7 +210,7 @@ class HSList(generic.ListView):
template_name = 'hs_list.html' template_name = 'hs_list.html'
def get_queryset(self): 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): def get_context_data(self, **kwargs):
context = super(HSList, self).get_context_data(**kwargs) context = super(HSList, self).get_context_data(**kwargs)

View File

@@ -52,7 +52,7 @@ class Profile(AbstractUser):
@property @property
def latest_events(self): 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 @classmethod
def admins(cls): def admins(cls):
@@ -244,7 +244,7 @@ class EventManager(models.Manager):
(models.Q(dry_hire=True, checked_in_by__isnull=True) & ( (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.BOOKED) | models.Q(status=Event.CONFIRMED))) | # Active dry hire GT
models.Q(status=Event.CANCELLED, start_date__gte=timezone.now()) # Canceled but not started 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 return events
@@ -345,7 +345,7 @@ class Event(models.Model, RevisionMixin):
@property @property
def sum_total(self): 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'), sum_total=models.Sum(models.F('cost') * models.F('quantity'),
output_field=models.DecimalField(max_digits=10, decimal_places=2)) output_field=models.DecimalField(max_digits=10, decimal_places=2))
)['sum_total'] )['sum_total']
@@ -706,6 +706,10 @@ class RiskAssessment(models.Model, RevisionMixin):
('review_riskassessment', 'Can review Risk Assessments') ('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 @property
def event_size(self): def event_size(self):
# Confirm event size. Check all except generators, since generators entails outside # Confirm event size. Check all except generators, since generators entails outside
@@ -788,6 +792,10 @@ class EventChecklist(models.Model, RevisionMixin):
inverted_fields = [] 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: class Meta:
ordering = ['event'] ordering = ['event']
permissions = [ permissions = [

View File

@@ -41,7 +41,7 @@ class RigboardIndex(generic.TemplateView):
context = super(RigboardIndex, self).get_context_data(**kwargs) context = super(RigboardIndex, self).get_context_data(**kwargs)
# call out method to get current events # 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" context['page_title'] = "Rigboard"
return context return context

View File

@@ -21,7 +21,7 @@
<th scope="col">Event</th> <th scope="col">Event</th>
{# mmm hax #} {# mmm hax #}
{% if object_list.0 != None %} {% if object_list.0 != None %}
{% for field in fields %} {% for field in object_list.0.fields %}
<th scope="col">{{ object_list.0|verbose_name:field|title }}</th> <th scope="col">{{ object_list.0|verbose_name:field|title }}</th>
{% endfor %} {% endfor %}
{% endif %} {% endif %}
@@ -33,7 +33,7 @@
<tr class="{% if object.reviewed_by %}table-success{%endif%}"> <tr class="{% if object.reviewed_by %}table-success{%endif%}">
{# General #} {# General #}
<th scope="row"><a href="{% url 'event_detail' object.event.pk %}">{{ object.event }}</a></th> <th scope="row"><a href="{% url 'event_detail' object.event.pk %}">{{ object.event }}</a></th>
{% for field in fields %} {% for field in object_list.0.fields %}
<td>{{ object|get_field:field }}</td> <td>{{ object|get_field:field }}</td>
{% endfor %} {% endfor %}
{# Buttons #} {# Buttons #}

View File

@@ -42,7 +42,7 @@
<td>{{ invoice.event.start_date }}</td> <td>{{ invoice.event.start_date }}</td>
<td>{{ invoice.invoice_date }}</td> <td>{{ invoice.invoice_date }}</td>
<td> <td>
{{ invoice.balance|floatformat:2 }} £{{ invoice.balance|floatformat:2 }}
{% if not invoice.event.internal %} {% if not invoice.event.internal %}
<br /> <br />
<span class="text-muted">{{ invoice.event.purchase_order }}</span> <span class="text-muted">{{ invoice.event.purchase_order }}</span>

View File

@@ -53,7 +53,7 @@
{% endif %} {% endif %}
</td> </td>
<td> <td>
{{ event.sum_total|floatformat:2 }} £{{ event.sum_total|floatformat:2 }}
<br /> <br />
<span class="text-muted">{% if not event.internal %}{{ event.purchase_order }}{% endif %}</span> <span class="text-muted">{% if not event.internal %}{{ event.purchase_order }}{% endif %}</span>
</td> </td>

View File

@@ -39,12 +39,12 @@ class AssetList(LoginRequiredMixin, generic.ListView):
# TODO Feedback to user when search fails # TODO Feedback to user when search fails
query_string = form.cleaned_data['q'] or "" query_string = form.cleaned_data['q'] or ""
if len(query_string) == 0: if len(query_string) == 0:
queryset = self.model.objects.all().select_related('category', 'status') queryset = self.model.objects.all()
elif len(query_string) >= 3: elif len(query_string) >= 3:
queryset = self.model.objects.filter( 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: 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']: if form.cleaned_data['category']:
queryset = queryset.filter(category__in=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( queryset = queryset.filter(
status__in=models.AssetStatus.objects.filter(should_show=True)) status__in=models.AssetStatus.objects.filter(should_show=True))
return queryset return queryset.select_related('category', 'status')
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(AssetList, self).get_context_data(**kwargs) context = super(AssetList, self).get_context_data(**kwargs)
@@ -180,7 +180,7 @@ class AssetAuditList(AssetList):
# TODO Refresh this when the modal is submitted # TODO Refresh this when the modal is submitted
def get_queryset(self): def get_queryset(self):
self.form = forms.AssetSearchForm(data=self.request.GET) 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): def get_context_data(self, **kwargs):
context = super(AssetAuditList, self).get_context_data(**kwargs) context = super(AssetAuditList, self).get_context_data(**kwargs)
@@ -288,7 +288,9 @@ class CableTypeList(generic.ListView):
model = models.CableType model = models.CableType
template_name = 'cable_type_list.html' template_name = 'cable_type_list.html'
paginate_by = 40 paginate_by = 40
# ordering = ['__str__']
def get_queryset(self):
return self.model.objects.select_related('plug', 'socket')
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)