Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: admin perf optimization for course-discovery #4496

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
115 changes: 113 additions & 2 deletions course_discovery/apps/course_metadata/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from django.conf import settings
from django.contrib import admin, messages
from django.contrib.admin.utils import model_ngettext
from django.db.models import Prefetch
from django.db.utils import IntegrityError
from django.forms import CheckboxSelectMultiple, ModelForm
from django.http import HttpResponseRedirect
Expand Down Expand Up @@ -85,6 +86,9 @@ class SeatInline(admin.TabularInline):
readonly_fields = ('_upgrade_deadline', )
raw_id_fields = ('draft_version', 'currency')

def get_queryset(self, request):
return super().get_queryset(request).select_related('draft_version', 'currency')


class PositionInline(admin.TabularInline):
model = Position
Expand Down Expand Up @@ -135,6 +139,10 @@ class CourseAdmin(DjangoObjectActions, SimpleHistoryAdmin):
autocomplete_fields = ['canonical_course_run']
change_actions = ('course_skills', 'refresh_course_skills')

def get_queryset(self, request):
queryset = super().get_queryset(request)
return queryset.select_related('canonical_course_run').prefetch_related('location_restriction')

def get_search_results(self, request, queryset, search_term):
queryset, may_have_duplicates = super().get_search_results(request, queryset, search_term)
if request.GET.get('app_label') == learner_pathway_app_name:
Expand Down Expand Up @@ -223,15 +231,18 @@ class CourseEditorAdmin(admin.ModelAdmin):
@admin.register(CourseEntitlement)
class CourseEntitlementAdmin(SimpleHistoryAdmin):
list_display = ['course', 'get_course_key', 'mode', 'draft']
raw_id_fields = ('course', 'draft_version',)
search_fields = ['course__title', 'course__key']

@admin.display(
description='Course key'
)
def get_course_key(self, obj):
return obj.course.key

raw_id_fields = ('course', 'draft_version',)
search_fields = ['course__title', 'course__key']
def get_queryset(self, request):
queryset = super().get_queryset(request)
return queryset.select_related('course', 'mode', 'partner')


@admin.register(Mode)
Expand All @@ -242,6 +253,7 @@ class ModeAdmin(admin.ModelAdmin):
@admin.register(Track)
class TrackAdmin(admin.ModelAdmin):
list_display = ['mode', 'seat_type']
list_select_related = ['seat_type', 'mode']


@admin.register(CourseRunType)
Expand Down Expand Up @@ -287,6 +299,12 @@ class CourseRunAdmin(SimpleHistoryAdmin):
save_error = False
form = CourseRunAdminForm

def get_queryset(self, request):
qs = super().get_queryset(request)
return qs.select_related(
'course', 'draft_version', 'language', 'type'
)

def get_readonly_fields(self, request, obj=None):
"""
Make UUID field editable for draft if flag is enabled.
Expand Down Expand Up @@ -391,6 +409,23 @@ class ProgramAdmin(DjangoObjectActions, SimpleHistoryAdmin):

save_error = False

def get_queryset(self, request):
queryset = super().get_queryset(request)
queryset = queryset.select_related(
'partner',
'type'
).prefetch_related(
'courses',
'authoring_organizations',
'credit_backing_organizations',
Prefetch(
'type__translations',
queryset=ProgramTypeTranslation.objects.filter(language_code='en'),
to_attr='prefetched_translations'
)
)
return queryset

def get_readonly_fields(self, request, obj=None):
"""
Make product_source field readonly if program obj is already created. In case a product without product_source
Expand Down Expand Up @@ -492,6 +527,15 @@ class PathwayAdmin(admin.ModelAdmin):
def get_programs(self, obj):
return [*obj.programs.all()]

def get_queryset(self, request):
queryset = super().get_queryset(request)
queryset = queryset.select_related('partner').prefetch_related(
Prefetch('programs', queryset=Program.objects.prefetch_related(
'courses__course_runs',
))
)
return queryset


@admin.register(ProgramType)
class ProgramTypeAdmin(TranslatableAdmin):
Expand Down Expand Up @@ -537,6 +581,10 @@ class AdditionalPromoAreaAdmin(admin.ModelAdmin):
list_display = ('title', 'description', 'courses')
search_fields = ('description',)

def get_queryset(self, request):
queryset = super().get_queryset(request)
return queryset.prefetch_related('extra_description')

def courses(self, obj):
return ', '.join([
course.key for course in obj.extra_description.all()
Expand All @@ -548,6 +596,17 @@ class FactAdmin(admin.ModelAdmin):
list_display = ('heading', 'blurb', 'courses')
search_fields = ('heading', 'blurb',)

def get_queryset(self, request):
queryset = super().get_queryset(request)
queryset = queryset.prefetch_related(
Prefetch(
"related_course_additional_metadata",
queryset=AdditionalMetadata.objects.prefetch_related("related_courses"),
)
)

return queryset

def courses(self, obj):

def _get_course_keys(additional_metadata_object):
Expand All @@ -563,6 +622,10 @@ class CertificateInfoAdmin(admin.ModelAdmin):
list_display = ('heading', 'blurb', 'courses')
search_fields = ('heading', 'blurb',)

def get_queryset(self, request):
queryset = super().get_queryset(request)
return queryset.prefetch_related('related_course_additional_metadata__related_courses')

def courses(self, obj):

def _get_course_keys(additional_metadata_object):
Expand All @@ -582,6 +645,17 @@ class AdditionalMetadataAdmin(admin.ModelAdmin):
search_fields = ('external_identifier', 'external_url')
list_filter = ('product_status', )

def get_queryset(self, request):
queryset = super().get_queryset(request)
return queryset.prefetch_related(
'related_courses',
'facts',
).select_related(
'taxi_form',
'product_meta',
'certificate_info',
)

def courses(self, obj):
return ', '.join([
course.key for course in obj.related_courses.all()
Expand Down Expand Up @@ -642,6 +716,10 @@ class SubjectAdmin(TranslatableAdmin):
readonly_fields = ('uuid',)
search_fields = ('uuid', 'name', 'slug',)

def get_queryset(self, request):
queryset = super().get_queryset(request)
return queryset.select_related('partner').prefetch_related('translations')


@admin.register(Topic)
class TopicAdmin(TranslatableAdmin):
Expand All @@ -660,6 +738,14 @@ class PersonAdmin(admin.ModelAdmin):
readonly_fields = ('uuid',)
search_fields = ('uuid', 'salutation', 'family_name', 'given_name', 'slug',)

def get_queryset(self, request):
queryset = super().get_queryset(request)
queryset = queryset.select_related(
'partner',
'bio_language',
)
return queryset


@admin.register(Position)
class PositionAdmin(admin.ModelAdmin):
Expand Down Expand Up @@ -696,6 +782,16 @@ class LevelTypeAdmin(SortableAdminMixin, TranslatableAdmin):
search_fields = ('name_t',)
fields = ('name_t',)

def get_queryset(self, request):
queryset = super().get_queryset(request)
queryset = queryset.prefetch_related(
Prefetch('translations', queryset=LevelTypeTranslation.objects.all(), to_attr='translated_names')
)
return queryset

def name_t(self, obj):
return obj.translated_names[0].name_t if obj.translated_names else obj.name


class CurriculumProgramMembershipInline(admin.TabularInline):
model = CurriculumProgramMembership
Expand Down Expand Up @@ -781,11 +877,17 @@ class IconTextPairingInline(admin.StackedInline):
class DegreeDeadlineAdmin(admin.ModelAdmin):
list_display = ('degree', 'semester', 'name', 'date', 'time')

def get_queryset(self, request):
return super().get_queryset(request).select_related('degree')


@admin.register(DegreeCost)
class DegreeCostAdmin(admin.ModelAdmin):
list_display = ('degree', 'description', 'amount')

def get_queryset(self, request):
return super().get_queryset(request).select_related('degree')


class DegreeDeadlineInlineAdmin(admin.StackedInline):
model = DegreeDeadline
Expand All @@ -805,6 +907,9 @@ class DegreeAdditionalMetadataInlineAdmin(admin.StackedInline):
class DegreeAdditionalMetadataAdmin(admin.ModelAdmin):
list_display = ('degree', 'external_url', 'external_identifier', 'organic_url')

def get_queryset(self, request):
return super().get_queryset(request).select_related('degree')


@admin.register(Specialization)
class SpecializationAdmin(admin.ModelAdmin):
Expand Down Expand Up @@ -842,6 +947,9 @@ class DegreeAdmin(admin.ModelAdmin):
)
actions = ['publish_degrees', 'unpublish_degrees', 'display_degrees_on_org_page', 'hide_degrees_on_org_page']

def get_queryset(self, request):
return super().get_queryset(request).prefetch_related('additional_metadata')

def change_degree_status(self, request, queryset, status):
"""
Changes the status of a degree.
Expand Down Expand Up @@ -1051,6 +1159,9 @@ class RestrictedCourseRunAdmin(admin.ModelAdmin):
list_display = ['course_run', 'restriction_type']
search_fields = ['course_run__key', 'restriction_type']

def get_queryset(self, request):
return super().get_queryset(request).select_related('course_run__course')


class CourseReviewAdmin(admin.ModelAdmin):
"""
Expand Down
Loading