Skip to content

Commit

Permalink
fix(periods): performance improvement to avoid nplus queries
Browse files Browse the repository at this point in the history
  • Loading branch information
llazzaro committed Jan 29, 2023
1 parent 5d92415 commit d889b00
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 5 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG
@@ -1,3 +1,7 @@
0.10.1 - 2023-01-29

- Periods performance improvement avoid nplus queries

0.10.0 - 2022-08-21
===================

Expand Down
9 changes: 5 additions & 4 deletions schedule/models/events.py
Expand Up @@ -598,10 +598,11 @@ class Meta:

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if not self.title and self.event_id:
self.title = self.event.title
if not self.description and self.event_id:
self.description = self.event.description
event = kwargs.get("event", None)
if not self.title and event:
self.title = event.title
if not self.description and event:
self.description = event.description

def moved(self):
return self.original_start != self.start or self.original_end != self.end
Expand Down
40 changes: 39 additions & 1 deletion tests/test_periods.py
Expand Up @@ -2,10 +2,12 @@

import pytz
from django.conf import settings
from django.db import connection
from django.test import TestCase
from django.test.utils import override_settings
from django.test.utils import CaptureQueriesContext, override_settings

from schedule.models import Calendar, Event, Rule
from schedule.models.events import Occurrence
from schedule.periods import Day, Month, Period, Week, Year


Expand Down Expand Up @@ -38,6 +40,42 @@ def test_get_occurrences(self):
],
)

def test_nplus_one_queries_event_period(self):
"""Reproduces bug 420 occurences without title or desc will generate additional queries
to retrieve the event model
"""
rule = Rule.objects.create(frequency="WEEKLY")
cal = Calendar.objects.get(name="MyCal")

event = Event.objects.create(
title="TEST",
start=datetime.datetime(2008, 1, 5, 8, 0, tzinfo=pytz.utc),
end=datetime.datetime(2023, 1, 5, 9, 0, tzinfo=pytz.utc),
end_recurring_period=datetime.datetime(2008, 5, 5, 0, 0, tzinfo=pytz.utc),
rule=rule,
calendar=cal,
)
for _ in range(0, 21):
# lets set occ without title and desc to use the event.title or event.desc
Occurrence.objects.create(
event=event,
start=datetime.datetime(2008, 1, 7, 8, 0, tzinfo=pytz.utc),
end=datetime.datetime(2008, 1, 7, 8, 0, tzinfo=pytz.utc),
original_start=datetime.datetime(2008, 1, 7, 8, 0, tzinfo=pytz.utc),
original_end=datetime.datetime(2008, 1, 7, 8, 0, tzinfo=pytz.utc),
)
period = Period(
events=[event],
start=datetime.datetime(2008, 1, 4, 7, 0, tzinfo=pytz.utc),
end=datetime.datetime(2023, 1, 21, 7, 0, tzinfo=pytz.utc),
)
with CaptureQueriesContext(connection) as ctx:
for occurrence in period.get_occurrences():
pass

executed_queries = len(ctx.captured_queries)
assert executed_queries == 1, len(ctx.captured_queries)

def test_get_occurrences_with_sorting_options(self):
period = Period(
events=Event.objects.all(),
Expand Down

0 comments on commit d889b00

Please sign in to comment.