From dc25c3b93892704697af360baffb331467b9b13f Mon Sep 17 00:00:00 2001 From: Justin Walgran Date: Fri, 17 May 2019 10:42:51 -0700 Subject: [PATCH] Use some read only fields in the Django admin The Facility, FacilityListItem, and FacilityMatch admin were loading combo boxes with all possible related objects. With a database populated with 10s of thousands of records this would make admin page requests so slow that the ECS task would be terminated. This commit fixes that by simply making the related fields read only. This works because we would not want to adjust these specific foreign key relationships anyway. While making some fields read only we also took the opportunity to also make the JSON status fields read only and add a helper to render them in a more readable way. --- CHANGELOG.md | 2 ++ src/django/api/admin.py | 41 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9dc858b57..ddc6bf21c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Fixed +- Made some fields read only in the Django admin to prevent slow page loads resulting in service interruptions. [#527](https://github.com/open-apparel-registry/open-apparel-registry/pull/527) + ### Security diff --git a/src/django/api/admin.py b/src/django/api/admin.py index 2807c0e6e..0db46327f 100644 --- a/src/django/api/admin.py +++ b/src/django/api/admin.py @@ -1,5 +1,8 @@ +import json + from django.contrib import admin from django.contrib.auth.admin import UserAdmin +from django.utils.safestring import mark_safe from simple_history.admin import SimpleHistoryAdmin from api import models @@ -15,12 +18,44 @@ class OarUserAdmin(UserAdmin): class FacilityHistoryAdmin(SimpleHistoryAdmin): - history_list_display = ['name', 'address', 'location'] + history_list_display = ('name', 'address', 'location') + + readonly_fields = ('created_from',) + + +class FacilityListItemAdmin(admin.ModelAdmin): + exclude = ('processing_results',) + readonly_fields = ('facility_list', 'facility', + 'pretty_processing_results') + + def pretty_processing_results(self, instance): + # The processing_results field is populated exclusively from processing + # code so we are not in danger of rendering potentially unsafe user + # submitted content + return mark_safe('
{}
'.format( + json.dumps(instance.processing_results, indent=2))) + + pretty_processing_results.short_description = 'Processing results' + + +class FacilityMatchAdmin(admin.ModelAdmin): + exclude = ('results',) + readonly_fields = ('facility_list_item', 'facility', + 'confidence', 'status', 'pretty_results') + + def pretty_results(self, instance): + # The status field is populated exclusively from processing code so we + # are not in danger of rendering potentially unsafe user submitted + # content + return mark_safe('
{}
'.format( + json.dumps(instance.results, indent=2))) + + pretty_results.short_description = 'Results' admin.site.register(models.User, OarUserAdmin) admin.site.register(models.Contributor) admin.site.register(models.FacilityList) -admin.site.register(models.FacilityListItem) +admin.site.register(models.FacilityListItem, FacilityListItemAdmin) admin.site.register(models.Facility, FacilityHistoryAdmin) -admin.site.register(models.FacilityMatch) +admin.site.register(models.FacilityMatch, FacilityMatchAdmin)