From 7954617a0593632d749d7e8b60beab2aae1669ba Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Wed, 17 Aug 2011 01:26:23 +0200 Subject: New page ISO Overview ISO Overview shows a simple list of all the ISOs that are available and how many times they've been tested successfully or have failed. Signed-off-by: Tom Willemsen Signed-off-by: Dan McGee --- releng/views.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'releng/views.py') diff --git a/releng/views.py b/releng/views.py index 1d4a0b5e..d90a5b9a 100644 --- a/releng/views.py +++ b/releng/views.py @@ -1,5 +1,6 @@ from django import forms from django.conf import settings +from django.db.models import Count from django.http import Http404 from django.shortcuts import get_object_or_404, redirect from django.views.generic.simple import direct_to_template @@ -138,4 +139,17 @@ def test_results_for(request, option, value): def submit_test_thanks(request): return direct_to_template(request, "releng/thanks.html", None) +def iso_overview(request): + isos = Iso.objects.all().order_by('-pk') + successes = dict(Iso.objects.values_list('pk').filter(test__success=True).annotate(ct=Count('test'))) + failures = dict(Iso.objects.values_list('pk').filter(test__success=False).annotate(ct=Count('test'))) + for iso in isos: + iso.successes = successes.get(iso.pk, 0) + iso.failures = failures.get(iso.pk, 0) + + context = { + 'isos': isos + } + return direct_to_template(request, 'releng/iso_overview.html', context) + # vim: set ts=4 sw=4 et: -- cgit v1.2.3-54-g00ecf From 61311701a51cc5b060d5baa56536805aa271f9d6 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Wed, 17 Aug 2011 08:11:23 -0500 Subject: Add architecture to releng results listing Signed-off-by: Dan McGee --- releng/views.py | 5 +++-- templates/releng/result_list.html | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'releng/views.py') diff --git a/releng/views.py b/releng/views.py index d90a5b9a..796fc044 100644 --- a/releng/views.py +++ b/releng/views.py @@ -115,7 +115,7 @@ def test_results_overview(request): def test_results_iso(request, iso_id): iso = get_object_or_404(Iso, pk=iso_id) - test_list = iso.test_set.all() + test_list = iso.test_set.select_related() context = { 'iso_name': iso.name, 'test_list': test_list @@ -127,7 +127,8 @@ def test_results_for(request, option, value): raise Http404 option_model = getattr(Test, option).field.rel.to real_value = get_object_or_404(option_model, pk=value) - test_list = real_value.test_set.order_by('-iso__name', '-pk') + test_list = real_value.test_set.select_related().order_by( + '-iso__name', '-pk') context = { 'option': option, 'value': real_value, diff --git a/templates/releng/result_list.html b/templates/releng/result_list.html index b3ae025b..a343257e 100644 --- a/templates/releng/result_list.html +++ b/templates/releng/result_list.html @@ -12,9 +12,10 @@

Results for: - + + @@ -24,6 +25,7 @@

Results for:

+ {% endfor %} -- cgit v1.2.3-54-g00ecf From c80afa08c7aec23984e84bfb3ab5683c9c392115 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Wed, 17 Aug 2011 09:01:07 -0500 Subject: releng: refactor results overview page for performance Use some annotation stuff and trickeration to reduce the number of queries we need on the results overview page by quite a bit. Signed-off-by: Dan McGee --- releng/models.py | 26 -------------------------- releng/views.py | 49 +++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 41 insertions(+), 34 deletions(-) (limited to 'releng/views.py') diff --git a/releng/models.py b/releng/models.py index 3afef55e..a958288b 100644 --- a/releng/models.py +++ b/releng/models.py @@ -10,36 +10,10 @@ class IsoOption(models.Model): def __unicode__(self): return self.name - def get_test_result(self, success): - try: - return self.test_set.filter(success=success).select_related( - 'iso').latest('iso__id').iso - except Test.DoesNotExist: - return None - - def get_last_success(self): - return self.get_test_result(True) - - def get_last_failure(self): - return self.get_test_result(False) - class Meta: abstract = True class RollbackOption(IsoOption): - def get_rollback_test_result(self, success): - try: - return self.rollback_test_set.filter(success=success).select_related( - 'iso').latest('iso__id').iso - except Test.DoesNotExist: - return None - - def get_last_rollback_success(self): - return self.get_rollback_test_result(True) - - def get_last_rollback_failure(self): - return self.get_rollback_test_result(False) - class Meta: abstract = True diff --git a/releng/views.py b/releng/views.py index 796fc044..7f895a45 100644 --- a/releng/views.py +++ b/releng/views.py @@ -1,6 +1,6 @@ from django import forms from django.conf import settings -from django.db.models import Count +from django.db.models import Count, Max from django.http import Http404 from django.shortcuts import get_object_or_404, redirect from django.views.generic.simple import direct_to_template @@ -85,18 +85,49 @@ def calculate_option_overview(field_name): 'is_rollback': is_rollback, 'values': [] } + if not is_rollback: + successes = dict(model.objects.values_list('pk').filter( + test__success=True).annotate(latest=Max('test__iso__id'))) + failures = dict(model.objects.values_list('pk').filter( + test__success=False).annotate(latest=Max('test__iso__id'))) + else: + successes = dict(model.objects.values_list('pk').filter( + rollback_test_set__success=True).annotate( + latest=Max('rollback_test_set__iso__id'))) + failures = dict(model.objects.values_list('pk').filter( + rollback_test_set__success=False).annotate( + latest=Max('rollback_test_set__iso__id'))) + for value in model.objects.all(): - data = { 'value': value } - if is_rollback: - data['success'] = value.get_last_rollback_success() - data['failure'] = value.get_last_rollback_failure() - else: - data['success'] = value.get_last_success() - data['failure'] = value.get_last_failure() + data = { + 'value': value, + 'success': successes.get(value.pk), + 'failure': failures.get(value.pk), + } option['values'].append(data) return option +def options_fetch_iso(options): + '''Replaces the Iso PK with a full Iso model object in a list of options + used on the overview page. We do it this way to only have to query the Iso + table once rather than once per option.''' + # collect all necessary Iso PKs + all_pks = set() + for option in options: + all_pks.update(v['success'] for v in option['values']) + all_pks.update(v['failure'] for v in option['values']) + + all_pks.discard(None) + all_isos = Iso.objects.in_bulk(all_pks) + + for option in options: + for value in option['values']: + value['success'] = all_isos.get(value['success']) + value['failure'] = all_isos.get(value['failure']) + + return options + def test_results_overview(request): # data structure produced: # [ { option, name, is_rollback, values: [ { value, success, failure } ... ] } ... ] @@ -107,6 +138,8 @@ def test_results_overview(request): for field in fields: all_options.append(calculate_option_overview(field)) + all_options = options_fetch_iso(all_options) + context = { 'options': all_options, 'iso_url': settings.ISO_LIST_URL, -- cgit v1.2.3-54-g00ecf From 871cf5ad2d8a97c2c9f9f20e237999acbf5e5f2a Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Wed, 17 Aug 2011 20:53:57 -0500 Subject: Use verbose name for releng options display So we see something like 'Hardware Type' instead of 'Hardware_Type'. Signed-off-by: Dan McGee --- releng/views.py | 5 +++-- templates/releng/result_list.html | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'releng/views.py') diff --git a/releng/views.py b/releng/views.py index 7f895a45..2b3d0936 100644 --- a/releng/views.py +++ b/releng/views.py @@ -81,7 +81,7 @@ def calculate_option_overview(field_name): is_rollback = field_name.startswith('rollback_') option = { 'option': model, - 'name': field_name, + 'name': model._meta.verbose_name, 'is_rollback': is_rollback, 'values': [] } @@ -159,11 +159,12 @@ def test_results_for(request, option, value): if option not in Test._meta.get_all_field_names(): raise Http404 option_model = getattr(Test, option).field.rel.to + option_model.verbose_name = option_model._meta.verbose_name real_value = get_object_or_404(option_model, pk=value) test_list = real_value.test_set.select_related().order_by( '-iso__name', '-pk') context = { - 'option': option, + 'option': option_model, 'value': real_value, 'value_id': value, 'test_list': test_list diff --git a/templates/releng/result_list.html b/templates/releng/result_list.html index 7f9ed452..0233bf8c 100644 --- a/templates/releng/result_list.html +++ b/templates/releng/result_list.html @@ -3,7 +3,7 @@ {% block content %}

Results for: - {% if option %}{{ option|title }}: {{ value }}{% endif %} + {% if option %}{{ option.verbose_name|title }}: {{ value }}{% endif %} {{ iso_name|default:"" }}

-- cgit v1.2.3-54-g00ecf
IsoISO Submitted By Date SubmittedArchitecture Success
{{ test.iso.name }} {{ test.user_name }} {{ test.created|date }}{{ test.architecture }} {{ test.success|yesno }}