Compare commits

...

3 Commits

4 changed files with 45 additions and 34 deletions

View File

@ -1,4 +1,5 @@
import sys import sys
import traceback
from django.views.debug import ExceptionReporter from django.views.debug import ExceptionReporter
from django.core import mail from django.core import mail
@ -9,6 +10,7 @@ class AdminEmailReporter:
pass pass
def report(self): def report(self):
try:
reporter = ExceptionReporter(None, *sys.exc_info()) reporter = ExceptionReporter(None, *sys.exc_info())
message = f"Failed to run task\n{reporter.get_traceback_text()}" message = f"Failed to run task\n{reporter.get_traceback_text()}"
html_message = reporter.get_traceback_html() html_message = reporter.get_traceback_html()
@ -18,3 +20,5 @@ class AdminEmailReporter:
# fail_silently=True, # fail_silently=True,
html_message=html_message, html_message=html_message,
) )
except Exception:
print(traceback.format_exc())

View File

@ -0,0 +1,24 @@
# Generated by Django 5.0.1 on 2024-01-03 19:22
import django.db.models.expressions
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("membershipworks", "0006_eventext_instructor_flat_rate_and_more"),
]
operations = [
migrations.AddField(
model_name="eventmeetingtime",
name="duration",
field=models.GeneratedField(
db_persist=False,
expression=django.db.models.expressions.CombinedExpression(
models.F("end"), "-", models.F("start")
),
output_field=models.DurationField(),
),
),
]

View File

@ -415,13 +415,7 @@ class EventInstructor(models.Model):
class EventExtManager(models.Manager["EventExt"]): class EventExtManager(models.Manager["EventExt"]):
def get_queryset(self) -> models.QuerySet["EventExt"]: def get_queryset(self) -> models.QuerySet["EventExt"]:
return ( return super().get_queryset().annotate(duration=Sum("meeting_times__duration"))
super()
.get_queryset()
.annotate(duration=Sum(F("meeting_times__end") - F("meeting_times__start")))
)
# TODO: use simpler expression when GeneratedField fixed
# return super().get_queryset().annotate(duration=Sum("meeting_times__duration"))
class EventExt(Event): class EventExt(Event):
@ -446,29 +440,18 @@ class EventExt(Event):
verbose_name = "event" verbose_name = "event"
class EventMeetingTimeManager(models.Manager["EventMeetingTime"]):
def get_queryset(self) -> models.QuerySet["EventMeetingTime"]:
return super().get_queryset().annotate(duration=F("end") - F("start"))
class EventMeetingTime(models.Model): class EventMeetingTime(models.Model):
objects = EventMeetingTimeManager()
event = models.ForeignKey( event = models.ForeignKey(
EventExt, on_delete=models.CASCADE, related_name="meeting_times" EventExt, on_delete=models.CASCADE, related_name="meeting_times"
) )
start = models.DateTimeField() start = models.DateTimeField()
end = models.DateTimeField() end = models.DateTimeField()
# TODO: Should use generated field instead of manager, but this is duration = models.GeneratedField(
# broken due to current Django bug, pending next release (> 5.0) expression=F("end") - F("start"),
# ref: https://code.djangoproject.com/ticket/35019 output_field=models.DurationField(),
db_persist=False,
# duration = models.GeneratedField( )
# expression=F("end") - F("start"),
# output_field=models.DurationField(),
# db_persist=False,
# )
class Meta: class Meta:
constraints = [ constraints = [

View File

@ -22,7 +22,7 @@ GROUPS_REGEX = "|".join(
# A group name must start and end with a letter, number or underscore. # A group name must start and end with a letter, number or underscore.
# In between additionally spaces, dashes and dots are allowed. # In between additionally spaces, dashes and dots are allowed.
def sanitize_group_name(name): def sanitize_group_name(name):
sanitized_body = re.sub(r"[^0-9A-Za-z_ -.]", ".", name) sanitized_body = re.sub(r"[^0-9A-Za-z_ -.]+", ".", name)
sanitized_start_end = re.sub("^[^0-9A-Za-z_]|[^0-9A-Za-z_]$", "_", sanitized_body) sanitized_start_end = re.sub("^[^0-9A-Za-z_]|[^0-9A-Za-z_]$", "_", sanitized_body)
return "MW_" + sanitized_start_end return "MW_" + sanitized_start_end
@ -30,7 +30,7 @@ def sanitize_group_name(name):
# From an API error message: "Username must only contain numbers, letters and dots!" # From an API error message: "Username must only contain numbers, letters and dots!"
def sanitize_user_name(name): def sanitize_user_name(name):
return re.sub(r"[^0-9a-z.]", ".", name.lower()).strip(".") return re.sub(r"[^0-9a-z.]+", ".", name.lower()).strip(".")
async def make_groups(udm): async def make_groups(udm):