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

Flexible end #541 #542

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
===================

- Periods performance improvement avoid nplus queries
- Make event.end optional so that it can later be updated with a known value

0.10.0 - 2022-08-21
===================
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,17 @@ Value is in seconds.
Default (two years):
62208000

### EVENT_END_DEFAULT_DURATION

An event can be created without an end date.
In this case the field default_end is set to True and this setting is used to supply an end date some time way into the future.

The value should be a dictionary of keywords for dateutil.relativedelta

Default (99 years):
```python
{"years": 99}
```

Contributing
============
Expand Down
11 changes: 11 additions & 0 deletions docs/settings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,14 @@ example::

get_events(request, calendar):
return calendar.event_set.all()

EVENT_END_DEFAULT_DURATION
--------------------------

An event can be created without an end date.
In this case the field default_end is set to True and this setting is used to supply an end date some time way into the future.

The value should be a dictionary of keywords for dateutil.relativedelta

example:
{"years": 99}
4 changes: 4 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
python-dateutil~=2.7.3
setuptools~=45.2.0
pytz
coverage
1 change: 1 addition & 0 deletions schedule/migrations/0001_initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class Migration(migrations.Migration):
verbose_name="end",
),
),
("default_end", models.BooleanField(default=False)),
("title", models.CharField(max_length=255, verbose_name="title")),
(
"description",
Expand Down
24 changes: 24 additions & 0 deletions schedule/migrations/0015_alter_event_end.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Generated by Django 4.0.6 on 2022-09-10 15:18

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("schedule", "0014_use_autofields_for_pk"),
]

operations = [
migrations.AlterField(
model_name="event",
name="end",
field=models.DateTimeField(
blank=True,
db_index=True,
help_text="The end time must be later than the start time.",
null=True,
verbose_name="end",
),
),
]
28 changes: 28 additions & 0 deletions schedule/models/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import pytz
from dateutil import rrule
from dateutil.relativedelta import relativedelta
from django.conf import settings as django_settings
from django.contrib.contenttypes import fields
from django.contrib.contenttypes.models import ContentType
Expand All @@ -14,6 +15,7 @@

from schedule.models.calendars import Calendar
from schedule.models.rules import Rule
from schedule.settings import EVENT_END_DEFAULT_DURATION
from schedule.utils import OccurrenceReplacer

freq_dict_order = {
Expand Down Expand Up @@ -50,12 +52,38 @@ class Event(models.Model):
other models.
"""

@staticmethod
def end_of_time():
return datetime.datetime.today() + relativedelta(**EVENT_END_DEFAULT_DURATION)

def clean(self):
"""Ensure the end date is not given and optional end_recurring_period (if given) match"""
super().clean()
if self.end is None:
if self.end_recurring_period is not None:
self.end = self.end_recurring_period
else:
self.end = self.end_of_time()
self.default_end = True

if (
self.end_recurring_period is not None
and self.end != self.end_recurring_period
):
end = min(self.end, self.end_recurring_period)
self.end = end
self.end_recurring_period = end
self.default_end = False

start = models.DateTimeField(_("start"), db_index=True)
end = models.DateTimeField(
_("end"),
db_index=True,
null=True,
blank=True,
help_text=_("The end time must be later than the start time."),
)
default_end = models.BooleanField(default=False)
title = models.CharField(_("title"), max_length=255)
description = models.TextField(_("description"), blank=True)
creator = models.ForeignKey(
Expand Down
5 changes: 5 additions & 0 deletions schedule/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,8 @@ def get_events(request, calendar):

# This name is used when a new event is created through selecting in fullcalendar
EVENT_NAME_PLACEHOLDER = getattr(settings, "EVENT_NAME_PLACEHOLDER", "Event Name")

# Default kw args to dateutuil.relativedelta to create a temporary end date if none given
EVENT_END_DEFAULT_DURATION = getattr(
settings, "EVENT_END_DEFAULT_DURATION", {"years": 99}
)