Deploy Django5 stuff on production #93

Merged
heinzel merged 11 commits from stage into production 2025-04-11 11:23:24 +02:00
53 changed files with 203 additions and 160 deletions

View File

@@ -10,11 +10,11 @@ For production use you surly want a real web server that supports WSGI
QUICK INSTALLATION FOR THE IMPATIENT QUICK INSTALLATION FOR THE IMPATIENT
==================================== ====================================
- python -m venv ./etc/python - python -m venv ./env/python
- source env/python/bin/activate - source env/python/bin/activate
- python -m pip install -r requirements.txt - python -m pip install -r requirements.txt
- python -m pip install -e . - python -m pip install -e .
- django-dav-events-admin setup ./env/django - django-dav-admin setup ./env/django
- python ./env/django/manage.py enable_module dav_auth - python ./env/django/manage.py enable_module dav_auth
- python ./env/django/manage.py enable_module dav_events - python ./env/django/manage.py enable_module dav_events
- python ./env/django/manage.py enable_module dav_registration - python ./env/django/manage.py enable_module dav_registration

View File

@@ -1 +0,0 @@
default_app_config = 'dav_auth.apps.AppConfig' # pylint: disable=invalid-name

View File

@@ -2,7 +2,7 @@ from django.contrib import admin
from django.contrib.auth.admin import GroupAdmin as _GroupAdmin from django.contrib.auth.admin import GroupAdmin as _GroupAdmin
from django.contrib.auth.models import Group from django.contrib.auth.models import Group
from django.contrib.auth.models import Permission from django.contrib.auth.models import Permission
from django.utils.translation import ugettext as _ from django.utils.translation import gettext as _
admin.site.unregister(Group) admin.site.unregister(Group)

View File

@@ -2,7 +2,7 @@
import logging import logging
from django import forms from django import forms
from django.contrib.auth import forms as auth_forms, password_validation from django.contrib.auth import forms as auth_forms, password_validation
from django.utils.translation import ugettext, ugettext_lazy as _ from django.utils.translation import gettext, gettext_lazy as _
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -48,7 +48,7 @@ class SetPasswordForm(forms.Form):
if password1 and password2: if password1 and password2:
if password1 != password2: if password1 != password2:
raise forms.ValidationError( raise forms.ValidationError(
ugettext('Passwörter stimmen nicht überein'), gettext('Passwörter stimmen nicht überein'),
code='password_mismatch', code='password_mismatch',
) )
return password2 return password2

View File

@@ -1,3 +1,4 @@
{ {
"url_prefix": "auth" "url_prefix": "auth",
"app_config": ".apps.AppConfig"
} }

View File

@@ -8,7 +8,13 @@
</button> </button>
<ul class="dropdown-menu dropdown-menu-right" aria-labelledby="user_dropdown_button"> <ul class="dropdown-menu dropdown-menu-right" aria-labelledby="user_dropdown_button">
<li><a href="{% url 'dav_auth:set_password' %}">{% trans 'Passwort ändern' %}</a></li> <li><a href="{% url 'dav_auth:set_password' %}">{% trans 'Passwort ändern' %}</a></li>
<li><a href="{% url 'dav_auth:logout' %}">{% trans 'Logout' %}</a></li> <li>
<form method="post" action="{% url 'dav_auth:logout' %}" class="navbar-form">
{% csrf_token %}
<button id="id_logout_button" type="submit" class="btn btn-sm btn-danger"
style="width: 100%;">{% trans "Logout" %}</button>
</form>
</li>
</ul> </ul>
</div> </div>
{% else %} {% else %}

View File

@@ -17,6 +17,10 @@ class SeleniumAuthMixin:
return driver return driver
def logout(self, driver): def logout(self, driver):
driver.get(self.complete_url(reverse('dav_auth:logout'))) #driver.get(self.complete_url(reverse('dav_auth:logout')))
dropdown_button = driver.find_element(By.ID, 'user_dropdown_button')
dropdown_button.click()
logout_button = driver.find_element(By.ID, 'id_logout_button')
logout_button.click()
self.wait_on_presence(driver, (By.CSS_SELECTOR, "#messages .alert-success")) self.wait_on_presence(driver, (By.CSS_SELECTOR, "#messages .alert-success"))
return driver return driver

View File

@@ -2,7 +2,7 @@
from unittest import skip from unittest import skip
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.core import mail as django_mail from django.core import mail as django_mail
from django.utils.translation import ugettext from django.utils.translation import gettext
from dav_base.tests.generic import FormDataSet, FormsTestCase from dav_base.tests.generic import FormDataSet, FormsTestCase
@@ -25,8 +25,8 @@ class LoginFormTestCase(FormsTestCase):
def test_labels(self): def test_labels(self):
form = self.form_class() form = self.form_class()
self.assertEqual(form.fields['username'].label, ugettext('E-Mail-Adresse')) self.assertEqual(form.fields['username'].label, gettext('E-Mail-Adresse'))
self.assertEqual(form.fields['password'].label, ugettext('Password')) self.assertEqual(form.fields['password'].label, gettext('Password'))
def test_required(self): def test_required(self):
form = self.form_class() form = self.form_class()
@@ -193,7 +193,7 @@ class CreateAndSendPasswordFormTestCase(FormsTestCase):
def test_labels(self): def test_labels(self):
form = self.form_class() form = self.form_class()
self.assertEqual(form.fields['username'].label, ugettext('E-Mail-Adresse')) self.assertEqual(form.fields['username'].label, gettext('E-Mail-Adresse'))
def test_required(self): def test_required(self):
form = self.form_class() form = self.form_class()

View File

@@ -2,7 +2,7 @@
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.test import tag from django.test import tag
from django.urls import reverse from django.urls import reverse
from django.utils.translation import ugettext from django.utils.translation import gettext
from selenium.webdriver.common.by import By from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.keys import Keys
@@ -105,7 +105,7 @@ class TestCase(ScreenshotTestCase):
# Click on 'set password' -> save set password page # Click on 'set password' -> save set password page
user_menu = c.find_element(By.CSS_SELECTOR, '#login-widget ul') user_menu = c.find_element(By.CSS_SELECTOR, '#login-widget ul')
link = user_menu.find_element(By.PARTIAL_LINK_TEXT, ugettext('Passwort ändern')) link = user_menu.find_element(By.PARTIAL_LINK_TEXT, gettext('Passwort ändern'))
link.click() link.click()
password_field = self.wait_on_presence(c, (By.ID, 'id_new_password')) password_field = self.wait_on_presence(c, (By.ID, 'id_new_password'))
self.save_screenshot('empty_set_password_form', sequence=sequence_name) self.save_screenshot('empty_set_password_form', sequence=sequence_name)
@@ -189,8 +189,10 @@ class TestCase(ScreenshotTestCase):
dropdown_button = self.wait_on_presence(c, (By.ID, 'user_dropdown_button')) dropdown_button = self.wait_on_presence(c, (By.ID, 'user_dropdown_button'))
dropdown_button.click() dropdown_button.click()
user_menu = c.find_element(By.CSS_SELECTOR, '#login-widget ul') user_menu = c.find_element(By.CSS_SELECTOR, '#login-widget ul')
link = user_menu.find_element(By.PARTIAL_LINK_TEXT, ugettext('Logout')) #link = user_menu.find_element(By.PARTIAL_LINK_TEXT, gettext('Logout'))
link.click() #link.click()
button = c.find_element(By.ID, 'id_logout_button')
button.click()
self.wait_until_stale(c, user_menu) self.wait_until_stale(c, user_menu)
self.save_screenshot('logout_succeed', sequence=sequence_name) self.save_screenshot('logout_succeed', sequence=sequence_name)
@@ -200,7 +202,7 @@ class TestCase(ScreenshotTestCase):
self.wait_on_presence(c, (By.ID, 'id_username')) self.wait_on_presence(c, (By.ID, 'id_username'))
# Locate password recreate link, click it -> save password recreate form # Locate password recreate link, click it -> save password recreate form
link = c.find_element(By.PARTIAL_LINK_TEXT, ugettext('Passwort vergessen')) link = c.find_element(By.PARTIAL_LINK_TEXT, gettext('Passwort vergessen'))
link.click() link.click()
username_field = self.wait_on_presence(c, (By.ID, 'id_username')) username_field = self.wait_on_presence(c, (By.ID, 'id_username'))
self.save_screenshot('empty_recreate_password_form', sequence=sequence_name) self.save_screenshot('empty_recreate_password_form', sequence=sequence_name)
@@ -212,7 +214,7 @@ class TestCase(ScreenshotTestCase):
self.save_screenshot('recreate_password_invalid_user', sequence=sequence_name) self.save_screenshot('recreate_password_invalid_user', sequence=sequence_name)
# Locate password recreate link, click it # Locate password recreate link, click it
link = c.find_element(By.PARTIAL_LINK_TEXT, ugettext('Passwort vergessen')) link = c.find_element(By.PARTIAL_LINK_TEXT, gettext('Passwort vergessen'))
link.click() link.click()
username_field = self.wait_on_presence(c, (By.ID, 'id_username')) username_field = self.wait_on_presence(c, (By.ID, 'id_username'))

View File

@@ -2,7 +2,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.test import SimpleTestCase, tag from django.test import SimpleTestCase, tag
from django.utils.translation import ugettext from django.utils.translation import gettext
from django.urls import reverse from django.urls import reverse
from selenium.common.exceptions import NoSuchElementException from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By from selenium.webdriver.common.by import By
@@ -20,7 +20,7 @@ class TemplatesTestCase(SimpleTestCase):
def test_recreate_link_in_login_form(self): def test_recreate_link_in_login_form(self):
login_url = reverse('dav_auth:login') login_url = reverse('dav_auth:login')
recreate_url = reverse('dav_auth:recreate_password') recreate_url = reverse('dav_auth:recreate_password')
text = ugettext('Passwort vergessen?') text = gettext('Passwort vergessen?')
html = '<a href="{url}">{text}</a>'.format(url=recreate_url, text=text) html = '<a href="{url}">{text}</a>'.format(url=recreate_url, text=text)
response = self.client.get(login_url) response = self.client.get(login_url)
self.assertInHTML(html, response.content.decode('utf-8')) self.assertInHTML(html, response.content.decode('utf-8'))

View File

@@ -6,7 +6,8 @@ from .. import views
class TestCase(UrlsTestCase): class TestCase(UrlsTestCase):
urls = ( urls = (
Url('/auth/login', 'dav_auth:login', views.LoginView.as_view()), Url('/auth/login', 'dav_auth:login', views.LoginView.as_view()),
Url('/auth/logout', 'dav_auth:logout', views.LogoutView.as_view(), status_code=302), Url('/auth/logout', 'dav_auth:logout', views.LogoutView.as_view(), status_code=302,
http_method='POST'),
Url('/auth/password', 'dav_auth:set_password', views.SetPasswordView.as_view(), Url('/auth/password', 'dav_auth:set_password', views.SetPasswordView.as_view(),
redirect='/auth/login?next=/auth/password'), redirect='/auth/login?next=/auth/password'),
Url('/auth/password/recreate', 'dav_auth:recreate_password', views.CreateAndSendPasswordView.as_view()), Url('/auth/password/recreate', 'dav_auth:recreate_password', views.CreateAndSendPasswordView.as_view()),

View File

@@ -4,7 +4,7 @@ from django.contrib.auth import get_user_model
from django.core import mail as django_mail from django.core import mail as django_mail
from django.shortcuts import resolve_url from django.shortcuts import resolve_url
from django.test import TestCase from django.test import TestCase
from django.utils.translation import ugettext from django.utils.translation import gettext
from django.urls import reverse from django.urls import reverse
from ..forms import LoginForm, SetPasswordForm, CreateAndSendPasswordForm from ..forms import LoginForm, SetPasswordForm, CreateAndSendPasswordForm
@@ -30,9 +30,9 @@ class ViewsTestCase(TestCase):
cls.recreate_password_url = reverse('dav_auth:recreate_password') cls.recreate_password_url = reverse('dav_auth:recreate_password')
# Some messages # Some messages
cls.wrong_credentials_message = ugettext('Benutzername oder Passwort falsch.') cls.wrong_credentials_message = gettext('Benutzername oder Passwort falsch.')
cls.logout_message = ugettext('Benutzer abgemeldet.') cls.logout_message = gettext('Benutzer abgemeldet.')
cls.set_password_message = ugettext('Passwort gespeichert.') cls.set_password_message = gettext('Passwort gespeichert.')
def setUp(self): def setUp(self):
super().setUp() super().setUp()
@@ -61,7 +61,7 @@ class ViewsTestCase(TestCase):
response = self.client.post(self.login_url, {'username': self.test_username, 'password': self.test_password}) response = self.client.post(self.login_url, {'username': self.test_username, 'password': self.test_password})
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertFormError(response, 'form', None, self.wrong_credentials_message) self.assertFormError(response.context['form'], None, self.wrong_credentials_message)
self.assertFalse(response.context['user'].is_authenticated, 'User is logged in') self.assertFalse(response.context['user'].is_authenticated, 'User is logged in')
def test_integrated_login_fail_with_wrong_credentials(self): def test_integrated_login_fail_with_wrong_credentials(self):
@@ -69,12 +69,12 @@ class ViewsTestCase(TestCase):
response = self.client.post(self.login_url, {'username': self.test_username, 'password': wrong_password}) response = self.client.post(self.login_url, {'username': self.test_username, 'password': wrong_password})
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertFormError(response, 'form', None, self.wrong_credentials_message) self.assertFormError(response.context['form'],None, self.wrong_credentials_message)
self.assertFalse(response.context['user'].is_authenticated, 'User is logged in') self.assertFalse(response.context['user'].is_authenticated, 'User is logged in')
def test_integrated_login_succeed(self): def test_integrated_login_succeed(self):
username = self.user.username username = self.user.username
message = ugettext('Benutzer angemeldet: %(username)s') % {'username': username} message = gettext('Benutzer angemeldet: %(username)s') % {'username': username}
response = self.client.post(self.login_url, {'username': username, 'password': self.test_password}) response = self.client.post(self.login_url, {'username': username, 'password': self.test_password})
self.assertEqual(response.status_code, 302) self.assertEqual(response.status_code, 302)
@@ -88,7 +88,7 @@ class ViewsTestCase(TestCase):
def test_integrated_logout(self): def test_integrated_logout(self):
self.client.login(username=self.test_username, password=self.test_password) self.client.login(username=self.test_username, password=self.test_password)
response = self.client.get(self.logout_url) response = self.client.post(self.logout_url)
self.assertEqual(response.status_code, 302) self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, self.logout_redirect_url) self.assertEqual(response.url, self.logout_redirect_url)

View File

@@ -1,12 +1,12 @@
from django.conf.urls import url from django.urls import re_path
from . import views from . import views
app_name = 'dav_auth' app_name = 'dav_auth'
urlpatterns = [ urlpatterns = [
url(r'^login$', views.LoginView.as_view(), name='login'), re_path(r'^login$', views.LoginView.as_view(), name='login'),
url(r'^logout$', views.LogoutView.as_view(), name='logout'), re_path(r'^logout$', views.LogoutView.as_view(), name='logout'),
url(r'^password$', views.SetPasswordView.as_view(), name='set_password'), re_path(r'^password$', views.SetPasswordView.as_view(), name='set_password'),
url(r'^password/recreate$', views.CreateAndSendPasswordView.as_view(), name='recreate_password'), re_path(r'^password/recreate$', views.CreateAndSendPasswordView.as_view(), name='recreate_password'),
] ]

View File

@@ -9,7 +9,7 @@ from django.http import HttpResponseRedirect
from django.shortcuts import resolve_url from django.shortcuts import resolve_url
from django.urls import reverse_lazy, reverse from django.urls import reverse_lazy, reverse
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.utils.translation import ugettext as _ from django.utils.translation import gettext as _
from django.views import generic from django.views import generic
from . import emails from . import emails
@@ -48,9 +48,10 @@ class LoginView(auth_views.LoginView):
class LogoutView(auth_views.LogoutView): class LogoutView(auth_views.LogoutView):
def get_next_page(self): @property
url = super().get_next_page() def next_page(self):
if not url and app_config.settings.logout_redirect_url: url = None
if app_config.settings.logout_redirect_url:
url = resolve_url(app_config.settings.logout_redirect_url) url = resolve_url(app_config.settings.logout_redirect_url)
return url return url

View File

@@ -1 +0,0 @@
default_app_config = 'dav_base.apps.AppConfig' # pylint: disable=invalid-name

View File

@@ -3,7 +3,7 @@ import os
import pkg_resources import pkg_resources
from django.conf import settings from django.conf import settings
from django.conf.urls import url as django_conf_url, include from django.urls import re_path, include
DJANGO_MAIN_MODULE = 'main' DJANGO_MAIN_MODULE = 'main'
MODULE_CONFIG_FILE_NAME = 'module_config.json' MODULE_CONFIG_FILE_NAME = 'module_config.json'
@@ -19,6 +19,7 @@ class ModuleMeta:
def __init__(self, package_name): def __init__(self, package_name):
self._package_name = package_name self._package_name = package_name
self._app_config = None
self._additional_apps = [] self._additional_apps = []
self._url_prefix = None self._url_prefix = None
self._load_from_package() self._load_from_package()
@@ -28,9 +29,19 @@ class ModuleMeta:
return t return t
@property @property
def app(self): def package(self):
return self._package_name return self._package_name
@property
def app(self):
if self._app_config:
app = self._app_config
if app.startswith('.'):
app = self._package_name + app
else:
app = self._package_name
return app
@property @property
def additional_apps(self): def additional_apps(self):
return self._additional_apps return self._additional_apps
@@ -50,7 +61,7 @@ class ModuleMeta:
def url_conf_pattern(self): def url_conf_pattern(self):
url_pattern = '^{}/'.format(self.url_prefix) url_pattern = '^{}/'.format(self.url_prefix)
url_conf = self._package_name + '.urls' url_conf = self._package_name + '.urls'
return django_conf_url(url_pattern, include(url_conf, self.url_namespace)) return re_path(url_pattern, include(url_conf, self.url_namespace))
def _load_from_package(self): def _load_from_package(self):
package_name = self._package_name package_name = self._package_name
@@ -61,6 +72,7 @@ class ModuleMeta:
def load_from_dict(self, meta_dict): def load_from_dict(self, meta_dict):
self._package_name = meta_dict.get('package', None) self._package_name = meta_dict.get('package', None)
self._app_config = meta_dict.get('app_config', None)
self._additional_apps = meta_dict.get('additional_apps', []) self._additional_apps = meta_dict.get('additional_apps', [])
self._url_prefix = meta_dict.get('url_prefix', None) self._url_prefix = meta_dict.get('url_prefix', None)
@@ -68,6 +80,8 @@ class ModuleMeta:
d = { d = {
'package': self._package_name, 'package': self._package_name,
} }
if self._app_config:
d['app_config'] = self._app_config
if self._additional_apps: if self._additional_apps:
d['additional_apps'] = self._additional_apps d['additional_apps'] = self._additional_apps
if self._url_prefix: if self._url_prefix:

View File

@@ -16,7 +16,7 @@ INSTALLED_APPS += [
'django_countries', 'django_countries',
# 'django_extensions', # 'django_extensions',
# Our main app # Our main app
'dav_base', 'dav_base.apps.AppConfig',
] ]
# Add apps from our modules # Add apps from our modules

View File

@@ -1,5 +1,5 @@
from django.conf import settings from django.conf import settings
from django.conf.urls import url, include from django.urls import re_path, include
urlpatterns = [] urlpatterns = []
@@ -8,5 +8,5 @@ for module_meta_obj in settings.MODULE_CONFIG.modules.values():
urlpatterns.append(module_meta_obj.url_conf_pattern) urlpatterns.append(module_meta_obj.url_conf_pattern)
urlpatterns += [ urlpatterns += [
url(r'^', include('dav_base.urls')) re_path(r'^', include('dav_base.urls'))
] ]

View File

@@ -171,6 +171,8 @@ class Url: # pylint: disable=too-few-public-methods
self.location = location self.location = location
self.name = name self.name = name
self.func = func self.func = func
self.http_method = kwargs.get('http_method', "GET")
self.post_data = kwargs.get('post_data', {})
self.redirect = kwargs.get('redirect', False) self.redirect = kwargs.get('redirect', False)
self.status_code = kwargs.get('status_code', 200) self.status_code = kwargs.get('status_code', 200)
self.follow = kwargs.get('follow', False) self.follow = kwargs.get('follow', False)
@@ -182,7 +184,12 @@ class UrlsTestCase(TestCase):
def test_locations(self): def test_locations(self):
for url in self.urls: for url in self.urls:
if url.location: if url.location:
if url.http_method == "GET":
response = self.client.get(url.location, follow=url.follow) response = self.client.get(url.location, follow=url.follow)
elif url.http_method == "POST":
response = self.client.post(url.location, data=url.post_data, follow=url.follow)
else: # pragma: no cover
raise NotImplementedError("Method {} is not supported".format(url.http_method))
if url.redirect: if url.redirect:
self.assertRedirects(response, url.redirect) self.assertRedirects(response, url.redirect)
@@ -198,7 +205,13 @@ class UrlsTestCase(TestCase):
def test_names(self): def test_names(self):
for url in self.urls: for url in self.urls:
if url.name: if url.name:
response = self.client.get(reverse(url.name), follow=url.follow) location = reverse(url.name)
if url.http_method == "GET":
response = self.client.get(location, follow=url.follow)
elif url.http_method == "POST":
response = self.client.post(location, data=url.post_data, follow=url.follow)
else: # pragma: no cover
raise NotImplementedError("Method {} is not supported".format(url.http_method))
if url.redirect: if url.redirect:
self.assertRedirects(response, url.redirect) self.assertRedirects(response, url.redirect)

View File

@@ -1,11 +1,11 @@
from django.conf.urls import url from django.urls import re_path
from django.contrib import admin from django.contrib import admin
from django.views import generic from django.views import generic
from . import views from . import views
urlpatterns = [ urlpatterns = [
url(r'^$', views.RootView.as_view(), name='root'), re_path(r'^$', views.RootView.as_view(), name='root'),
url(r'^css-demo$', generic.TemplateView.as_view(template_name='dav_base/css_demo.html'), name='css-demo'), re_path(r'^css-demo$', generic.TemplateView.as_view(template_name='dav_base/css_demo.html'), name='css-demo'),
url(r'^djangoadmin/', admin.site.urls), re_path(r'^djangoadmin/', admin.site.urls),
] ]

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.core.validators import RegexValidator from django.core.validators import RegexValidator
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
DAVNumberValidator = RegexValidator(r'^' DAVNumberValidator = RegexValidator(r'^'

View File

@@ -15,7 +15,7 @@ class RootView(generic.TemplateView):
root_url_name = '%s:%s' % (module_meta_obj.url_namespace, root_url_name) root_url_name = '%s:%s' % (module_meta_obj.url_namespace, root_url_name)
try: try:
reverse(root_url_name) reverse(root_url_name)
root_urls.append((module_meta_obj.app, root_url_name)) root_urls.append((module_meta_obj.package, root_url_name))
except NoReverseMatch: except NoReverseMatch:
pass pass

View File

@@ -1 +0,0 @@
default_app_config = 'dav_event_office.apps.AppConfig' # pylint: disable=invalid-name

View File

@@ -1,3 +1,4 @@
{ {
"url_prefix": "office/events" "url_prefix": "office/events",
"app_config": ".apps.AppConfig"
} }

View File

@@ -1,12 +1,12 @@
from django.conf.urls import url from django.urls import re_path
from . import views from . import views
app_name = 'dav_event_office' app_name = 'dav_event_office'
urlpatterns = [ urlpatterns = [
url(r'^home$', views.HomeView.as_view(), name='root'), re_path(r'^home$', views.HomeView.as_view(), name='root'),
url(r'^participants$', views.ParticipantListView.as_view(), name='participant-list'), re_path(r'^participants$', views.ParticipantListView.as_view(), name='participant-list'),
url(r'^$', views.EventListView.as_view(), name='event-list'), re_path(r'^$', views.EventListView.as_view(), name='event-list'),
url(r'^(?P<pk>\d+)/', views.EventDetailView.as_view(), name='event-detail'), re_path(r'^(?P<pk>\d+)/', views.EventDetailView.as_view(), name='event-detail'),
] ]

View File

@@ -1 +0,0 @@
default_app_config = 'dav_events.apps.AppConfig' # pylint: disable=invalid-name

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django_countries import Countries from django_countries import Countries
CHOICE_FIELD_MAX_LENGTH = 25 CHOICE_FIELD_MAX_LENGTH = 25

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
from dav_events.config import FieldInitial from dav_events.config import FieldInitial
# E-Mails # E-Mails

View File

@@ -6,7 +6,7 @@ import re
from babel.dates import format_date from babel.dates import format_date
from django import forms from django import forms
from django.apps import apps from django.apps import apps
from django.utils.translation import get_language, ugettext, ugettext_lazy as _ from django.utils.translation import get_language, gettext, gettext_lazy as _
from django_countries.fields import Country, LazyTypedChoiceField from django_countries.fields import Country, LazyTypedChoiceField
from datetimewidget.widgets import DateWidget, TimeWidget, DateTimeWidget from datetimewidget.widgets import DateWidget, TimeWidget, DateTimeWidget
from six import string_types from six import string_types
@@ -840,7 +840,7 @@ class ChargesForm(EventCreateForm):
additional_costs_text = u'' additional_costs_text = u''
if transport != 'coach': if transport != 'coach':
additional_costs_text += ugettext(u'Fahrtkosten') additional_costs_text += gettext(u'Fahrtkosten')
if transport == 'public': if transport == 'public':
pubtrans_planned = True pubtrans_planned = True
else: else:
@@ -852,7 +852,7 @@ class ChargesForm(EventCreateForm):
if accommodation != 'NONE': if accommodation != 'NONE':
if additional_costs_text: if additional_costs_text:
additional_costs_text += u', ' additional_costs_text += u', '
additional_costs_text += ugettext(u'Unterkunft und Verpflegung') additional_costs_text += gettext(u'Unterkunft und Verpflegung')
else: else:
ndays = 1 ndays = 1
@@ -901,7 +901,7 @@ class ChargesForm(EventCreateForm):
self.fields['trainer1_reward'].initial = trainer1_reward self.fields['trainer1_reward'].initial = trainer1_reward
self.fields['trainer23_reward'].initial = trainer23_reward self.fields['trainer23_reward'].initial = trainer23_reward
self.fields['pubtrans_bonus'].widget.attrs['title'] = ugettext(u'Der Bonus wird nachträglich' self.fields['pubtrans_bonus'].widget.attrs['title'] = gettext(u'Der Bonus wird nachträglich'
u' auf Meldung der Tourenleitung' u' auf Meldung der Tourenleitung'
u' verrechnet und ist noch nicht' u' verrechnet und ist noch nicht'
u' in den hier dargestellten Zahlen enthalten.') u' in den hier dargestellten Zahlen enthalten.')
@@ -941,7 +941,7 @@ class ChargesForm(EventCreateForm):
) )
) )
self.fields['additional_costs'].widget.attrs['placeholder'] = ugettext(u'Kann freigelassen werden') self.fields['additional_costs'].widget.attrs['placeholder'] = gettext(u'Kann freigelassen werden')
self.fields['additional_costs'].initial = additional_costs_text self.fields['additional_costs'].initial = additional_costs_text
@@ -1011,32 +1011,32 @@ class DescriptionForm(EventCreateForm):
if mode == 'training': if mode == 'training':
# Titelprefix für Kurse # Titelprefix für Kurse
if level == 'family': if level == 'family':
value += u'%s' % ugettext(u'Familienkurs') value += u'%s' % gettext(u'Familienkurs')
elif level == 'beginner': elif level == 'beginner':
value += u'%s' % ugettext(u'Grundkurs') value += u'%s' % gettext(u'Grundkurs')
else: else:
value += u'%s' % ugettext(u'Aufbaukurs') value += u'%s' % gettext(u'Aufbaukurs')
if sport == 'B': if sport == 'B':
value += u' %s' % ugettext(u'Alpin') value += u' %s' % gettext(u'Alpin')
elif sport == 'K': elif sport == 'K':
if terrain == 'gym': if terrain == 'gym':
value += u' %s' % ugettext(u'Indoorklettern') value += u' %s' % gettext(u'Indoorklettern')
elif terrain == 'crag': elif terrain == 'crag':
value += u' %s' % ugettext(u'Fels') value += u' %s' % gettext(u'Fels')
elif terrain == 'alpine': elif terrain == 'alpine':
value += u' %s' % ugettext(u'Alpinklettern') value += u' %s' % gettext(u'Alpinklettern')
value += u': ...' value += u': ...'
elif sport == 'W': elif sport == 'W':
# Titelprefix für Wanderungen # Titelprefix für Wanderungen
if level == 'family': if level == 'family':
value += u'%s ...' % ugettext(u'Familienwanderung') value += u'%s ...' % gettext(u'Familienwanderung')
elif not last_day: elif not last_day:
value += u'%s ...' % ugettext(u'Tageswanderung') value += u'%s ...' % gettext(u'Tageswanderung')
elif level == 'family': elif level == 'family':
# Titelprefix für sonstige Familientouren # Titelprefix für sonstige Familientouren
value += u'%s: ...' % ugettext(u'Familientour') value += u'%s: ...' % gettext(u'Familientour')
if app_config.settings.forms_development_init: if app_config.settings.forms_development_init:
if not value: if not value:

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django import forms from django import forms
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
class RegistrationResponseForm(forms.Form): class RegistrationResponseForm(forms.Form):

View File

@@ -13,7 +13,7 @@ from django.contrib.auth import get_user_model
from django.urls import reverse from django.urls import reverse
from django.db import models from django.db import models
from django.template.loader import get_template from django.template.loader import get_template
from django.utils.translation import get_language, ugettext_lazy as _ from django.utils.translation import get_language, gettext_lazy as _
from django_countries.fields import Country, CountryField from django_countries.fields import Country, CountryField
from .. import choices from .. import choices

View File

@@ -1,6 +1,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
from ..validators import IdStringValidator from ..validators import IdStringValidator

View File

@@ -6,7 +6,7 @@ from django.contrib.auth import get_user_model
from django.urls import reverse from django.urls import reverse
from django.db import models from django.db import models
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext, ugettext_lazy as _ from django.utils.translation import gettext, gettext_lazy as _
from .event import Event from .event import Event
@@ -51,7 +51,7 @@ class OneClickAction(models.Model):
if self.done and not self.allow_repeat: if self.done and not self.allow_repeat:
result['context'] = { result['context'] = {
'status': 'warning', 'status': 'warning',
'message': ugettext('Diese Aktion hast du bereits ausgeführt.'), 'message': gettext('Diese Aktion hast du bereits ausgeführt.'),
} }
return result return result
@@ -78,7 +78,7 @@ class OneClickAction(models.Model):
flag = event.flags.filter(status__code=status_code).first() flag = event.flags.filter(status__code=status_code).first()
if flag: if flag:
message = (ugettext('Der Status wurde bereits' message = (gettext('Der Status wurde bereits'
' am %(date)s' ' am %(date)s'
' von %(user)s' ' von %(user)s'
' auf \'%(status)s\' gesetzt.') % { ' auf \'%(status)s\' gesetzt.') % {
@@ -88,7 +88,7 @@ class OneClickAction(models.Model):
}) })
else: else:
flag = event.workflow.update_status(status_code, user) flag = event.workflow.update_status(status_code, user)
message = (ugettext('Der Status wurde auf \'%(status)s\' gesetzt.') % message = (gettext('Der Status wurde auf \'%(status)s\' gesetzt.') %
{'status': flag.status.label}) {'status': flag.status.label})
result['context'] = { result['context'] = {
@@ -109,7 +109,7 @@ class OneClickAction(models.Model):
else: else:
result['context'] = { result['context'] = {
'status': 'danger', 'status': 'danger',
'message': ugettext('Invalid Command. Code on fire!'), 'message': gettext('Invalid Command. Code on fire!'),
} }
return result return result

View File

@@ -4,7 +4,7 @@ import datetime
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db import models from django.db import models
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
from dav_base.validators import DAVNumberValidator from dav_base.validators import DAVNumberValidator

View File

@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
from ..participant import AbstractParticipant from ..participant import AbstractParticipant

View File

@@ -1,3 +1,4 @@
{ {
"url_prefix": "events" "url_prefix": "events",
"app_config": ".apps.AppConfig"
} }

View File

@@ -1,9 +1,9 @@
from django.dispatch import Signal from django.dispatch import Signal
event_created = Signal(providing_args=['event']) event_created = Signal()
event_updated = Signal(providing_args=['event', 'diff', 'user']) event_updated = Signal()
event_status_updated = Signal(providing_args=['event', 'flag']) event_status_updated = Signal()
event_registration_closed = Signal(providing_args=['event', 'user']) event_registration_closed = Signal()
def signal_handler_for_event_update(sender, **kwargs): def signal_handler_for_event_update(sender, **kwargs):

View File

@@ -51,7 +51,7 @@
</li> </li>
</ul> </ul>
</div> </div>
<form action="" method="post"> <form id="id_event_update_form" action="" method="post">
{% csrf_token %} {% csrf_token %}
{% if is_realized %} {% if is_realized %}

View File

@@ -4,7 +4,7 @@ from django import template
from django.utils.html import format_html from django.utils.html import format_html
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext as _ from django.utils.translation import gettext as _
from ..models.eventchange import EventChange from ..models.eventchange import EventChange
from ..models.eventstatus import EventStatus, get_or_create_event_status from ..models.eventstatus import EventStatus, get_or_create_event_status

View File

@@ -5,7 +5,7 @@ import re
from django.apps import apps from django.apps import apps
from django.test import TestCase from django.test import TestCase
from django.urls import reverse from django.urls import reverse
from django.utils.translation import ugettext from django.utils.translation import gettext
from dav_base.tests.generic import EmailTestMixin from dav_base.tests.generic import EmailTestMixin
@@ -80,7 +80,7 @@ class ActionTestCase(EmailTestMixin, RoleMixin, EventMixin, TestCase):
content = response.content.decode('utf-8') content = response.content.decode('utf-8')
status_label = self.get_status_label(status_code) status_label = self.get_status_label(status_code)
message = ugettext('Der Status wurde auf \'%(status)s\' gesetzt.') % {'status': status_label} message = gettext('Der Status wurde auf \'%(status)s\' gesetzt.') % {'status': status_label}
html = message.replace('\'', '&#39;') html = message.replace('\'', '&#39;')
self.assertInHTML(html, content) self.assertInHTML(html, content)
self.assertRegex(content, r'alert-success') self.assertRegex(content, r'alert-success')
@@ -103,7 +103,7 @@ class ActionTestCase(EmailTestMixin, RoleMixin, EventMixin, TestCase):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
content = response.content.decode('utf-8') content = response.content.decode('utf-8')
html = ugettext('Diese Aktion hast du bereits ausgeführt.') html = gettext('Diese Aktion hast du bereits ausgeführt.')
self.assertInHTML(html, content) self.assertInHTML(html, content)
self.assertRegex(content, r'alert-warning') self.assertRegex(content, r'alert-warning')
@@ -112,13 +112,13 @@ class ActionTestCase(EmailTestMixin, RoleMixin, EventMixin, TestCase):
content = response.content.decode('utf-8') content = response.content.decode('utf-8')
status_label = self.get_status_label(status_code) status_label = self.get_status_label(status_code)
message = (ugettext('Der Status wurde bereits' message = (gettext('Der Status wurde bereits'
' am %(date)s' ' am %(date)s'
' von %(user)s' ' von %(user)s'
' auf \'%(status)s\' gesetzt.') % { ' auf \'%(status)s\' gesetzt.') % {
'status': status_label, 'status': status_label,
# 'date': datetime.datetime.now().strftime('%d.%m.%Y %H:%M:%S'), # 'date': datetime.datetime.now().strftime('%d.%m.%Y %H:%M:%S'),
'date': '\d{2}\.\d{2}\.\d{4} \d{2}:\d{2}:\d{2}', 'date': r'\d{2}\.\d{2}\.\d{4} \d{2}:\d{2}:\d{2}',
'user': user.get_full_name(), 'user': user.get_full_name(),
}) })
html = message.replace('\'', '&#x27;') html = message.replace('\'', '&#x27;')

View File

@@ -2,7 +2,7 @@
import time import time
from django.test import tag from django.test import tag
from django.urls import reverse from django.urls import reverse
from django.utils.translation import ugettext from django.utils.translation import gettext
from selenium.common.exceptions import NoSuchElementException from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.keys import Keys
@@ -528,7 +528,7 @@ class TestCase(SeleniumAuthMixin, RoleMixin, ScreenshotTestCase):
self.wait_until_stale(c, link) self.wait_until_stale(c, link)
action_tabs = c.find_element(By.CSS_SELECTOR, '.action-tabs > ul.nav-tabs') action_tabs = c.find_element(By.CSS_SELECTOR, '.action-tabs > ul.nav-tabs')
tab = action_tabs.find_element(By.LINK_TEXT, ugettext(u'Ändern')) tab = action_tabs.find_element(By.LINK_TEXT, gettext(u'Ändern'))
tab.click() tab.click()
self.wait_until_stale(c, tab) self.wait_until_stale(c, tab)
@@ -537,14 +537,14 @@ class TestCase(SeleniumAuthMixin, RoleMixin, ScreenshotTestCase):
if screenshots: if screenshots:
self.save_screenshot('edit-form', sequence=sequence_name) self.save_screenshot('edit-form', sequence=sequence_name)
button = panel.find_element(By.PARTIAL_LINK_TEXT, ugettext(u'Nächster Abschnitt')) button = panel.find_element(By.PARTIAL_LINK_TEXT, gettext(u'Nächster Abschnitt'))
button.click() button.click()
time.sleep(.5) time.sleep(.5)
if screenshots: if screenshots:
self.save_screenshot('edit-form', sequence=sequence_name) self.save_screenshot('edit-form', sequence=sequence_name)
button = c.find_element(By.CSS_SELECTOR, 'form button[type="submit"]') button = c.find_element(By.CSS_SELECTOR, '#id_event_update_form button[type="submit"]')
button.click() button.click()
self.wait_until_stale(c, button) self.wait_until_stale(c, button)
@@ -580,7 +580,7 @@ class TestCase(SeleniumAuthMixin, RoleMixin, ScreenshotTestCase):
if screenshots: if screenshots:
self.save_screenshot('accepted', sequence=sequence_name) self.save_screenshot('accepted', sequence=sequence_name)
link = c.find_element(By.LINK_TEXT, ugettext('Veranstaltungsliste')) link = c.find_element(By.LINK_TEXT, gettext('Veranstaltungsliste'))
link.click() link.click()
self.wait_until_stale(c, link) self.wait_until_stale(c, link)
if screenshots: if screenshots:
@@ -618,7 +618,7 @@ class TestCase(SeleniumAuthMixin, RoleMixin, ScreenshotTestCase):
if screenshots: if screenshots:
self.save_screenshot('confirmed_{}'.format(channel), sequence=sequence_name) self.save_screenshot('confirmed_{}'.format(channel), sequence=sequence_name)
link = c.find_element(By.LINK_TEXT, ugettext('Veranstaltungsliste')) link = c.find_element(By.LINK_TEXT, gettext('Veranstaltungsliste'))
link.click() link.click()
self.wait_until_stale(c, link) self.wait_until_stale(c, link)
if screenshots: if screenshots:
@@ -650,7 +650,7 @@ class TestCase(SeleniumAuthMixin, RoleMixin, ScreenshotTestCase):
if screenshots: if screenshots:
self.save_screenshot('confirmed_clearance', sequence=sequence_name) self.save_screenshot('confirmed_clearance', sequence=sequence_name)
link = c.find_element(By.LINK_TEXT, ugettext('Veranstaltungsliste')) link = c.find_element(By.LINK_TEXT, gettext('Veranstaltungsliste'))
link.click() link.click()
self.wait_until_stale(c, link) self.wait_until_stale(c, link)
if screenshots: if screenshots:
@@ -730,7 +730,7 @@ class TestCase(SeleniumAuthMixin, RoleMixin, ScreenshotTestCase):
button.click() button.click()
self.wait_until_stale(c, button) self.wait_until_stale(c, button)
link = c.find_element(By.PARTIAL_LINK_TEXT, ugettext(u'Veranstaltungsliste herunterladen')) link = c.find_element(By.PARTIAL_LINK_TEXT, gettext(u'Veranstaltungsliste herunterladen'))
link.click() link.click()
self.wait_until_stale(c, link) self.wait_until_stale(c, link)
self.save_screenshot('event_export_form') self.save_screenshot('event_export_form')

View File

@@ -1,20 +1,20 @@
from django.conf.urls import url from django.urls import re_path
from . import views from . import views
app_name = 'dav_events' app_name = 'dav_events'
urlpatterns = [ urlpatterns = [
url(r'^home$', views.base.HomeView.as_view(), name='root'), re_path(r'^home$', views.base.HomeView.as_view(), name='root'),
url(r'^$', views.events.EventListView.as_view(), name='list'), re_path(r'^$', views.events.EventListView.as_view(), name='list'),
url(r'^export$', views.events.EventListExportView.as_view(), name='list_export'), re_path(r'^export$', views.events.EventListExportView.as_view(), name='list_export'),
url(r'^create$', views.events.EventCreateView.as_view(), name='create'), re_path(r'^create$', views.events.EventCreateView.as_view(), name='create'),
url(r'^(?P<pk>\d+)/registrations', views.events.EventRegistrationsView.as_view(), name='registrations'), re_path(r'^(?P<pk>\d+)/registrations', views.events.EventRegistrationsView.as_view(), name='registrations'),
url(r'^(?P<pk>\d+)/status/(?P<status>[a-z0-9._-][a-z0-9._-]*)', re_path(r'^(?P<pk>\d+)/status/(?P<status>[a-z0-9._-][a-z0-9._-]*)',
views.events.EventUpdateStatusView.as_view(), name='updatestatus'), views.events.EventUpdateStatusView.as_view(), name='updatestatus'),
url(r'^(?P<pk>\d+)/edit', views.events.EventUpdateView.as_view(), name='update'), re_path(r'^(?P<pk>\d+)/edit', views.events.EventUpdateView.as_view(), name='update'),
url(r'^(?P<pk>\d+)/', views.events.EventDetailView.as_view(), name='detail'), re_path(r'^(?P<pk>\d+)/', views.events.EventDetailView.as_view(), name='detail'),
url(r'^registration/(?P<pk>\d+)/', views.events.RespondRegistrationView.as_view(), name='respond_registration'), re_path(r'^registration/(?P<pk>\d+)/', views.events.RespondRegistrationView.as_view(), name='respond_registration'),
url(r'^action/(?P<pk>[a-fA-F0-9]{8}-([a-fA-F0-9]{4}-){3}[a-fA-F0-9]{12})/', re_path(r'^action/(?P<pk>[a-fA-F0-9]{8}-([a-fA-F0-9]{4}-){3}[a-fA-F0-9]{12})/',
views.actions.OneClickActionRunView.as_view(), name='action_run'), views.actions.OneClickActionRunView.as_view(), name='action_run'),
] ]

View File

@@ -2,7 +2,7 @@ import logging
from django.contrib import messages from django.contrib import messages
from django.contrib.auth import login from django.contrib.auth import login
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.utils.translation import ugettext as _ from django.utils.translation import gettext as _
from django.views import generic from django.views import generic
from .. import models from .. import models

View File

@@ -14,7 +14,7 @@ from django.shortcuts import get_object_or_404
from django.urls import reverse, reverse_lazy from django.urls import reverse, reverse_lazy
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.utils.text import normalize_newlines from django.utils.text import normalize_newlines
from django.utils.translation import ugettext as _ from django.utils.translation import gettext as _
from django.views import generic from django.views import generic
from .. import choices from .. import choices

View File

@@ -5,7 +5,7 @@ import re
from django.apps import apps from django.apps import apps
from django.db.models.functions import Length from django.db.models.functions import Length
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
from . import emails from . import emails
from . import signals from . import signals
@@ -264,6 +264,9 @@ class BasicWorkflow(object):
status_list = [] status_list = []
self._check_status() self._check_status()
if not event.id:
return status_list
heaviest_flag = event.flags.order_by('status').last() heaviest_flag = event.flags.order_by('status').last()
if heaviest_flag: if heaviest_flag:
flags = [] flags = []

View File

@@ -1 +0,0 @@
default_app_config = 'dav_registration.apps.AppConfig' # pylint: disable=invalid-name

View File

@@ -2,7 +2,7 @@
import datetime import datetime
import logging import logging
from django import forms from django import forms
from django.utils.translation import ugettext, ugettext_lazy as _ from django.utils.translation import gettext, gettext_lazy as _
from .models import Registration from .models import Registration
@@ -40,14 +40,14 @@ class RegistrationForm(forms.ModelForm):
val = self.cleaned_data.get('year_of_birth') val = self.cleaned_data.get('year_of_birth')
if val > year_now: if val > year_now:
raise forms.ValidationError( raise forms.ValidationError(
ugettext('Dein Geburtsjahr liegt in der Zukunft?' gettext('Dein Geburtsjahr liegt in der Zukunft?'
' Das finden wir gut,' ' Das finden wir gut,'
' aber bitte melde dich besser mal per E-Mail bei uns.'), ' aber bitte melde dich besser mal per E-Mail bei uns.'),
code='to_young', code='to_young',
) )
elif val < (year_now - max_age): elif val < (year_now - max_age):
raise forms.ValidationError( raise forms.ValidationError(
ugettext('Du bist schon über %(max_age)d Jahre alt?' gettext('Du bist schon über %(max_age)d Jahre alt?'
' Das finden wir gut,' ' Das finden wir gut,'
' aber bitte melde dich besser mal per E-Mail bei uns.'), ' aber bitte melde dich besser mal per E-Mail bei uns.'),
params={'max_age': max_age}, params={'max_age': max_age},
@@ -63,7 +63,7 @@ class RegistrationForm(forms.ModelForm):
need_experience = False need_experience = False
if need_experience: if need_experience:
raise forms.ValidationError( raise forms.ValidationError(
ugettext('Die Tourenleiter*innen brauchen ein paar Angaben,' gettext('Die Tourenleiter*innen brauchen ein paar Angaben,'
' was du bereits kannst oder wie fit du bist.'), ' was du bereits kannst oder wie fit du bist.'),
code='need_experience', code='need_experience',
) )
@@ -73,7 +73,7 @@ class RegistrationForm(forms.ModelForm):
val = self.cleaned_data.get('privacy_policy_accepted') val = self.cleaned_data.get('privacy_policy_accepted')
if not val and self.instance.privacy_policy: if not val and self.instance.privacy_policy:
raise forms.ValidationError( raise forms.ValidationError(
ugettext('Wir müssen deine Daten leider speichern können,' gettext('Wir müssen deine Daten leider speichern können,'
' damit wir wissen, dass du teilnehmen möchtest.'), ' damit wir wissen, dass du teilnehmen möchtest.'),
code='privacy_policy_not_accepted', code='privacy_policy_not_accepted',
) )
@@ -84,7 +84,7 @@ class RegistrationForm(forms.ModelForm):
dav_member = self.cleaned_data.get('dav_member') dav_member = self.cleaned_data.get('dav_member')
dav_number = self.cleaned_data.get('dav_number') dav_number = self.cleaned_data.get('dav_number')
if dav_member and not dav_number: if dav_member and not dav_number:
error_msg = ugettext('Wenn du DAV Mitglied bist, brauchen wir deine Mitgliedsnummer.') error_msg = gettext('Wenn du DAV Mitglied bist, brauchen wir deine Mitgliedsnummer.')
self.add_error('not_dav_member', error_msg) self.add_error('not_dav_member', error_msg)
raise forms.ValidationError(error_msg, code='dav_number_missing') raise forms.ValidationError(error_msg, code='dav_number_missing')
return self.cleaned_data return self.cleaned_data

View File

@@ -6,7 +6,7 @@ from django.core.exceptions import ValidationError
from django.db import models from django.db import models
from django.urls import reverse from django.urls import reverse
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
from dav_base.validators import DAVNumberValidator from dav_base.validators import DAVNumberValidator
from dav_events.models.event import Event from dav_events.models.event import Event

View File

@@ -1,3 +1,4 @@
{ {
"url_prefix": "registration" "url_prefix": "registration",
"app_config": ".apps.AppConfig"
} }

View File

@@ -2,7 +2,7 @@ from django.dispatch import Signal
from . import emails from . import emails
registration_created = Signal(providing_args=['registration']) registration_created = Signal()
def send_emails_on_registration(sender, **kwargs): # pylint: disable=unused-argument def send_emails_on_registration(sender, **kwargs): # pylint: disable=unused-argument

View File

@@ -1,15 +1,15 @@
from django.conf.urls import url from django.urls import re_path
from . import views from . import views
app_name = 'dav_registration' app_name = 'dav_registration'
urlpatterns = [ urlpatterns = [
url(r'^$', views.RootView.as_view(), name='root'), re_path(r'^$', views.RootView.as_view(), name='root'),
url(r'^home/$', views.HomeView.as_view(), name='home'), re_path(r'^home/$', views.HomeView.as_view(), name='home'),
url(r'^event/$', views.EventListView.as_view(), name='events'), re_path(r'^event/$', views.EventListView.as_view(), name='events'),
url(r'^event/(?P<pk>\d+)/$', views.EventDetailView.as_view(), name='event'), re_path(r'^event/(?P<pk>\d+)/$', views.EventDetailView.as_view(), name='event'),
url(r'^event/(?P<pk>\d+)/registration/$', views.RegistrationView.as_view(), name='register'), re_path(r'^event/(?P<pk>\d+)/registration/$', views.RegistrationView.as_view(), name='register'),
url(r'^finished/$', views.RegistrationSuccessView.as_view(), name='registered'), re_path(r'^finished/$', views.RegistrationSuccessView.as_view(), name='registered'),
url(r'^api/v1/event/$', views.EventListAsJSONView, name='api_events'), re_path(r'^api/v1/event/$', views.EventListAsJSONView, name='api_events'),
] ]

View File

@@ -6,7 +6,7 @@ from django.contrib import messages
from django.db.models import Q from django.db.models import Q
from django.http import JsonResponse from django.http import JsonResponse
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.utils.translation import ugettext as _ from django.utils.translation import gettext as _
from django.views import generic from django.views import generic
from dav_events.choices import SPORT_CHOICES, LEVEL_CHOICES from dav_events.choices import SPORT_CHOICES, LEVEL_CHOICES

View File

@@ -1,5 +1,5 @@
babel babel
django<3.3 django<5.1
django-bootstrap3 django-bootstrap3
django-countries django-countries
django-datetime-widget2 django-datetime-widget2