From e9b6b46780643d6512f202dc42b10977c67b8272 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= Date: Sat, 31 Aug 2013 17:49:28 +0200 Subject: [PATCH] performance: refactor code shared by episode and emission into a mixin Cuts down a "Panik sur la ville" episode page from 585 to 23 queries. --- panikweb/views.py | 57 +++++++++++++++++------------------------------ 1 file changed, 21 insertions(+), 36 deletions(-) diff --git a/panikweb/views.py b/panikweb/views.py index d5fb40f..0d423cc 100644 --- a/panikweb/views.py +++ b/panikweb/views.py @@ -18,18 +18,14 @@ from emissions.models import Category, Emission, Episode, Diffusion, SoundFile, from emissions.utils import whatsonair, period_program -class EmissionDetailView(DetailView): - model = Emission - - def get_context_data(self, **kwargs): - context = super(EmissionDetailView, self).get_context_data(**kwargs) - context['sectionName'] = "Emissions" - context['schedules'] = Schedule.objects.select_related().filter(emission=self.object).order_by('datetime') +class EmissionMixin: + def get_emission_context(self, emission): + context = {} # get all episodes, with an additional attribute to get the date of # their first diffusion context['episodes'] = \ - Episode.objects.select_related().filter(emission=self.object + Episode.objects.select_related().filter(emission=emission ).extra(select={ 'first_diffusion': 'emissions_diffusion.datetime', }, @@ -43,7 +39,7 @@ class EmissionDetailView(DetailView): # get all related soundfiles in a single query soundfiles = {} for soundfile in SoundFile.objects.select_related().filter(podcastable=True, - fragment=False, episode__emission=self.object): + fragment=False, episode__emission=emission): soundfiles[soundfile.episode_id] = soundfile # replace dynamic property by a static attribute, to avoid database @@ -52,41 +48,30 @@ class EmissionDetailView(DetailView): episode.main_sound = soundfiles.get(episode.id) return context + + + +class EmissionDetailView(DetailView, EmissionMixin): + model = Emission + + def get_context_data(self, **kwargs): + context = super(EmissionDetailView, self).get_context_data(**kwargs) + context['sectionName'] = "Emissions" + context['schedules'] = Schedule.objects.select_related().filter(emission=self.object).order_by('datetime') + context.update(self.get_emission_context(self.object)) + return context emission = EmissionDetailView.as_view() -class EpisodeDetailView(DetailView): +class EpisodeDetailView(DetailView, EmissionMixin): model = Episode def get_context_data(self, **kwargs): context = super(EpisodeDetailView, self).get_context_data(**kwargs) context['sectionName'] = "Emissions" - context['diffusions'] = Diffusion.objects.filter(episode=self.object.id) - context['soundfiles'] = SoundFile.objects.filter(episode=self.object.id) + context['diffusions'] = Diffusion.objects.select_related().filter(episode=self.object.id) + context['soundfiles'] = SoundFile.objects.select_related().filter(episode=self.object.id) context['emission'] = Emission.objects.get(slug=self.kwargs.get('emission_slug')) - # get all episodes, with an additional attribute to get the date of - # their first diffusion - context['episodes'] = \ - Episode.objects.filter(emission=context['emission'] - ).extra(select={ - 'first_diffusion': 'emissions_diffusion.datetime', - }, - select_params=(False, True), - where=['''datetime = (SELECT MIN(datetime) - FROM emissions_diffusion - WHERE episode_id = emissions_episode.id)'''], - tables=['emissions_diffusion'], - ).order_by('-first_diffusion') - - # get all related soundfiles in a single query - soundfiles = {} - for soundfile in SoundFile.objects.filter(podcastable=True, - fragment=False, episode__emission=Emission.objects.get(slug=self.kwargs.get('emission_slug'))): - soundfiles[soundfile.episode_id] = soundfile - - # replace dynamic property by a static attribute, to avoid database - # lookups - for episode in context['episodes']: - episode.main_sound = soundfiles.get(episode.id) + context.update(self.get_emission_context(context['emission'])) return context episode = EpisodeDetailView.as_view() -- GitLab