From e3b6dfda761e0b03ee733ddf26cfe757545c92a3 Mon Sep 17 00:00:00 2001 From: Tobias Bengfort Date: Wed, 7 Apr 2021 20:13:06 +0200 Subject: [PATCH 1/2] Work around https://code.djangoproject.com/ticket/25287 --- castellum/appointments/forms.py | 8 ++--- castellum/utils/expressions.py | 64 +++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 castellum/utils/expressions.py diff --git a/castellum/appointments/forms.py b/castellum/appointments/forms.py index 08256a86a..5b8e473f7 100644 --- a/castellum/appointments/forms.py +++ b/castellum/appointments/forms.py @@ -29,6 +29,7 @@ from django.utils.translation import gettext_lazy as _ from castellum.pseudonyms.helpers import get_pseudonym from castellum.recruitment.models import Participation from castellum.utils import scheduler +from castellum.utils.expressions import MultiDurationExpr from castellum.utils.forms import DateTimeField from .models import MINUTE @@ -90,11 +91,10 @@ class AppointmentsForm(forms.ModelForm): qs = Appointment.objects\ .exclude(participation=self.instance)\ .filter(participation__status=Participation.INVITED)\ - .alias(end=models.ExpressionWrapper( + .alias( # corresponds to the Appointment.end property - models.F('start') + models.F('session__duration') * MINUTE, - output_field=models.DateTimeField(), - )) + end=MultiDurationExpr(models.F('start'), MINUTE, models.F('session__duration')), + ) for session, key, start, end in appointments: if session.resource and qs.filter( diff --git a/castellum/utils/expressions.py b/castellum/utils/expressions.py new file mode 100644 index 000000000..ffe544c2b --- /dev/null +++ b/castellum/utils/expressions.py @@ -0,0 +1,64 @@ +# (c) 2018-2021 +# MPIB , +# MPI-CBS , +# MPIP +# +# This file is part of Castellum. +# +# Castellum is free software; you can redistribute it and/or modify it +# under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# Castellum is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public +# License along with Castellum. If not, see +# . + +from django.db import models + + +class MultiDurationExpr(models.Expression): + """Work around https://code.djangoproject.com/ticket/25287""" + + def __init__(self, dt, duration, factor): + super().__init__(output_field=models.DateTimeField()) + self.dt = dt + self.duration = duration + self.factor = factor + + def get_source_expressions(self): + return [self.dt, self.factor] + + def set_source_expressions(self, exprs): + self.dt, self.factor = exprs + + def as_sql(self, *args, **kwargs): + expr = models.ExpressionWrapper( + self.dt + self.factor * self.duration, output_field=models.DateTimeField + ) + return expr.as_sql(*args, **kwargs) + + def as_sqlite(self, compiler, connection): + microseconds = int(self.duration.total_seconds() * 1_000_000) + + expressions = [] + expression_params = [] + + sql, params = compiler.compile(self.dt) + expressions.append(sql) + expression_params.extend(params) + + sql, params = compiler.compile(self.factor) + expressions.append(sql) + expression_params.extend(params) + + expressions.append('%s') + expression_params.append(microseconds) + + sql = "django_format_dtdelta('+', {}, {} * {})".format(*expressions) + return sql, expression_params -- GitLab From 3cace6887ba1e62dc7d25d220c977cba6bca1f58 Mon Sep 17 00:00:00 2001 From: Tobias Bengfort Date: Wed, 7 Apr 2021 20:24:40 +0200 Subject: [PATCH 2/2] use sqlite in development --- Makefile | 16 +++++----------- castellum/settings/development.py | 16 ++++------------ docker-compose.yml | 25 ------------------------- docs/development.md | 2 +- 4 files changed, 10 insertions(+), 49 deletions(-) delete mode 100644 docker-compose.yml diff --git a/Makefile b/Makefile index 2794a4aa5..5387156b9 100644 --- a/Makefile +++ b/Makefile @@ -5,18 +5,18 @@ MANAGEPY = $(VIRTUAL_ENV)/bin/python manage.py all: bootstrap run .PHONY: run -run: databases +run: $(MANAGEPY) runserver .PHONY: bootstrap bootstrap: install migrate populate castellum/locale/de/LC_MESSAGES/django.mo .PHONY: migrate -migrate: databases +migrate: $(MANAGEPY) migrateall .PHONY: populate -populate: databases +populate: $(MANAGEPY) loaddata groups timeslots study_types study_groups resources $(MANAGEPY) create_attribute_descriptions $(MANAGEPY) create_demo_users @@ -32,13 +32,7 @@ makemessages: .PHONY: remove_databases remove_databases: - docker-compose stop - docker-compose rm -f - -.PHONY: databases -databases: - docker-compose up -d - docker-compose up db_wait + rm -f db.sqlite3 contacts.sqlite3 .PHONY: reset_databases reset_databases: remove_databases migrate populate @@ -50,7 +44,7 @@ lint: npx eslint castellum .PHONY: test -test: databases +test: $(VIRTUAL_ENV)/bin/pytest --reuse-db --show-capture=no .PHONY: install diff --git a/castellum/settings/development.py b/castellum/settings/development.py index d19c257b0..64f07f12d 100644 --- a/castellum/settings/development.py +++ b/castellum/settings/development.py @@ -30,20 +30,12 @@ except ImportError: DATABASES = { 'default': { - 'ENGINE': 'django.db.backends.postgresql', - 'NAME': 'postgres', - 'USER': 'postgres', - 'PASSWORD': 'CHANGEME', - 'HOST': os.environ.get('DB_DEFAULT_HOST', 'localhost'), - 'PORT': '6670', + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR.parent / 'db.sqlite3', }, 'contacts': { - 'ENGINE': 'django.contrib.gis.db.backends.postgis', - 'NAME': 'postgres', - 'USER': 'postgres', - 'PASSWORD': 'CHANGEME', - 'HOST': os.environ.get('DB_CONTACTS_HOST', 'localhost'), - 'PORT': '6671', + 'ENGINE': 'django.contrib.gis.db.backends.spatialite', + 'NAME': BASE_DIR.parent / 'contacts.sqlite3', }, } diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 03ea112a4..000000000 --- a/docker-compose.yml +++ /dev/null @@ -1,25 +0,0 @@ -version: "3.0" - -services: - db_wait: - image: postgres - depends_on: - - db_default - - db_contacts - command: ["sh", "-c", "until pg_isready -h db_default && pg_isready -h db_contacts; do sleep 1; done"] - environment: - PGPORT: "5432" - PGUSER: "postgres" - PGPASSWORD: "CHANGEME" - db_default: - image: postgres - ports: - - "6670:5432" - environment: - POSTGRES_PASSWORD: "CHANGEME" - db_contacts: - image: postgis/postgis - ports: - - "6671:5432" - environment: - POSTGRES_PASSWORD: "CHANGEME" diff --git a/docs/development.md b/docs/development.md index 5ba27403c..fb1fb9b8e 100644 --- a/docs/development.md +++ b/docs/development.md @@ -2,7 +2,7 @@ The following commands will install everything and start a local testserver (on ubuntu): - sudo apt install python3-pip python3-venv npm make docker-compose gettext gdal-bin python3-psycopg2 + sudo apt install python3-pip python3-venv npm make gettext gdal-bin libsqlite3-mod-spatialite cd castellum make install_githooks make # start castellum -- GitLab