Somewhat optimised SQL on level detail

This commit is contained in:
2021-12-28 21:35:21 +00:00
parent 732affa0b2
commit 14b73f6f50
6 changed files with 15 additions and 37 deletions

12
Pipfile
View File

@@ -19,7 +19,7 @@ cssselect = "~=1.1.0"
cssutils = "~=1.0.2"
dj-database-url = "~=0.5.0"
dj-static = "~=0.0.6"
Django = "~=3.1.12"
Django = "~=3.2"
django-debug-toolbar = "~=3.2"
django-filter = "~=2.4.0"
django-ical = "~=1.7.1"
@@ -89,14 +89,8 @@ pytest-django = "*"
pluggy = "*"
pytest-splinter = "*"
pytest = "*"
pytest-xdist = {extras = [ "psutil",], version = "*"}
PyPOM = {extras = [ "splinter",], version = "*"}
[requires]
python_version = "3.9"
[dev-packages.pytest-xdist]
extras = [ "psutil",]
version = "*"
[dev-packages.PyPOM]
extras = [ "splinter",]
version = "*"

View File

@@ -260,3 +260,5 @@ USE_GRAVATAR = True
TERMS_OF_HIRE_URL = "http://www.nottinghamtec.co.uk/terms.pdf"
AUTHORISATION_NOTIFICATION_ADDRESS = 'productions@nottinghamtec.co.uk'
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'

View File

@@ -18,10 +18,7 @@ class Trainee(Profile, RevisionMixin):
return [level for level in TrainingLevel.objects.all() if level.percentage_complete(self) > 0]
def level_qualifications(self, only_confirmed=False):
levels = self.levels.all()
if only_confirmed:
levels = levels.exclude(confirmed_on__isnull=True)
return levels.select_related('level')
return self.levels.all().filter(confirmed_on__isnull=only_confirmed).select_related('level')
@property
def is_supervisor(self):
@@ -38,8 +35,7 @@ class Trainee(Profile, RevisionMixin):
return self.qualifications_obtained.filter(depth=depth).select_related('item', 'trainee', 'supervisor')
def is_user_qualified_in(self, item, required_depth):
qual = self.qualifications_obtained.filter(item=item).first() # this is a somewhat ghetto version of get_or_none
return qual is not None and qual.depth >= required_depth
return self.qualifications_obtained.values('item', 'depth').filter(item=item).filter(depth__gte=required_depth).first() is not None # this is a somewhat ghetto version of get_or_none
def get_absolute_url(self):
return reverse('trainee_detail', kwargs={'pk': self.pk})
@@ -93,8 +89,8 @@ class TrainingItemQualification(models.Model):
(PASSED_OUT, 'Passed Out'),
)
item = models.ForeignKey('TrainingItem', on_delete=models.RESTRICT)
trainee = models.ForeignKey('Trainee', related_name='qualifications_obtained', on_delete=models.RESTRICT)
depth = models.IntegerField(choices=CHOICES)
trainee = models.ForeignKey('Trainee', related_name='qualifications_obtained', on_delete=models.RESTRICT)
date = models.DateField()
# TODO Remember that some training is external. Support for making an organisation the trainer?
supervisor = models.ForeignKey('Trainee', related_name='qualifications_granted', on_delete=models.RESTRICT)
@@ -189,18 +185,8 @@ class TrainingLevel(models.Model, RevisionMixin):
def passed_out_requirements(self):
return self.get_requirements_of_depth(TrainingItemQualification.PASSED_OUT)
def get_related_level(self, dif):
if (level == 0 and dif < 0) or (level == 2 and dif > 0):
return None
return TrainingLevel.objects.get(department=self.department, level=self.level+dif)
def get_common_competencies(self):
if is_common_competencies:
return self
return TrainingLevel.objects.get(level=self.level, department=None)
def percentage_complete(self, user): # FIXME
needed_qualifications = self.requirements.all().select_related()
def percentage_complete(self, user):
needed_qualifications = self.requirements.all().select_related('item')
relavant_qualifications = 0.0
# TODO Efficiency...
for req in needed_qualifications:

View File

@@ -70,7 +70,7 @@
<div class="alert alert-warning mx-auto">No qualifications in any levels yet...did someone forget to fill out the paperwork?</div>
{% endfor %}
</ul>
<h3>In Progress</h3>
<h3 class="col-12 pt-2">In Progress</h3>
<div class="card-columns">
{% for level in started_levels %}
{% percentage_complete level object as completion %}

View File

@@ -26,7 +26,7 @@
<th scope="row" class="align-middle" id="cell_name">{{ object.item }}</th>
<td class="table-{% colour_from_depth object.depth %}">{{ object.get_depth_display }}</td>
<td>{{ object.date }}</td>
<td>{{ object.supervisor }}</td>
<td><a href="{{ object.supervisor.get_absolute_url}}">{{ object.supervisor }}</a></td>
<td>{{ object.notes }}</td>
</tr>
{% empty %}

View File

@@ -7,7 +7,7 @@ from PyRIGS.views import OEmbedView, is_ajax, ModalURLMixin
from training import models, forms
from django.utils import timezone
from django.db import transaction
from django.db.models import Q, Count
from django.db.models import Q, Count, OuterRef, F, Subquery, Window
from users import views
@@ -37,12 +37,8 @@ class TraineeDetail(views.ProfileDetail):
else:
context["page_title"] = "{}'s Training Record".format(self.object.first_name + " " + self.object.last_name)
context["started_levels"] = self.object.started_levels()
context["completed_levels"] = self.object.level_qualifications()
context["completed_levels"] = self.object.level_qualifications().select_related('level')
context["categories"] = models.TrainingCategory.objects.all().prefetch_related('items')
choices = models.TrainingItemQualification.CHOICES
context["depths"] = choices
for i in [x for x, _ in choices]:
context[str(i)] = self.object.get_records_of_depth(i)
return context
@@ -101,7 +97,7 @@ class TraineeList(generic.ListView):
# not an integer
pass
return self.model.objects.filter(filter).annotate(num_qualifications=Count('qualifications_obtained')).order_by('-num_qualifications').prefetch_related('levels', 'qualifications_obtained')
return self.model.objects.filter(filter).annotate(num_qualifications=Count('qualifications_obtained')).order_by('-num_qualifications').prefetch_related('levels', 'qualifications_obtained', 'qualifications_obtained__item')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)