Refactor: split code into several django apps (we call them modules).
This commit is contained in:
1 parent
c23dc33d4e
commit
0d5a8c65e3
81 files changed
+739
-332
No files matched your search
@@ -0,0 +1 @@
|
|||||||
|
default_app_config = 'dav_auth.apps.AppConfig'
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
from dav_base.config.apps import AppConfig as _AppConfig, DefaultSetting
|
||||||
|
|
||||||
|
DEFAULT_SETTINGS = (
|
||||||
|
DefaultSetting('login_redirect_url', 'root'),
|
||||||
|
DefaultSetting('logout_redirect_url', 'root'),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class AppConfig(_AppConfig):
|
||||||
|
name = 'dav_auth'
|
||||||
|
verbose_name = u'DAV Benutzerverwaltung'
|
||||||
|
default_settings = DEFAULT_SETTINGS
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
# LOGIN_REDIRECT_URL = 'root'
|
||||||
|
# LOGOUT_REDIRECT_URL = 'root'
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from dav_base.emails import AbstractMail
|
||||||
|
|
||||||
|
|
||||||
|
class PasswordSetEmail(AbstractMail):
|
||||||
|
_subject = u'Zugangsdaten'
|
||||||
|
_template_name = 'dav_auth/emails/password_set.txt'
|
||||||
|
|
||||||
|
def __init__(self, user, password):
|
||||||
|
self._user = user
|
||||||
|
self._password = password
|
||||||
|
|
||||||
|
def _get_recipients(self):
|
||||||
|
r = u'{fullname} <{email}>'.format(fullname=self._user.get_full_name(),
|
||||||
|
email=self._user.email)
|
||||||
|
return [r]
|
||||||
|
|
||||||
|
def _get_context_data(self, extra_context=None):
|
||||||
|
context = super(PasswordSetEmail, self)._get_context_data(extra_context=extra_context)
|
||||||
|
context.update({
|
||||||
|
'fullname': self._user.get_full_name(),
|
||||||
|
'username': self._user.username,
|
||||||
|
'password': self._password
|
||||||
|
})
|
||||||
|
return context
|
||||||
File renamed without changes.
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"url_prefix": "auth"
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{% extends "dav_base/base.html" %}
|
||||||
+1
-1
@@ -3,4 +3,4 @@ Hallo {{ fullname }},
|
|||||||
Benutzername: {{ username }}
|
Benutzername: {{ username }}
|
||||||
Passwort: {{ password }}
|
Passwort: {{ password }}
|
||||||
|
|
||||||
URL: {{ base_url }}{% url 'dav_events:home' %}
|
URL: {{ base_url }}{% url 'root' %}
|
||||||
+3
-3
@@ -1,4 +1,4 @@
|
|||||||
{% extends "dav_events/base.html" %}
|
{% extends "dav_auth/base.html" %}
|
||||||
{% load bootstrap3 %}
|
{% load bootstrap3 %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
@@ -15,13 +15,13 @@
|
|||||||
<form action="" method="post">
|
<form action="" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{% bootstrap_form form %}
|
{% bootstrap_form form %}
|
||||||
<div class="pull-right"><a href="{% url 'dav_events:reset_password' %}">{% trans 'Passwort vergessen?' %}</a></div>
|
<div class="pull-right"><a href="{% url 'dav_auth:reset_password' %}">{% trans 'Passwort vergessen?' %}</a></div>
|
||||||
{% buttons %}
|
{% buttons %}
|
||||||
<button type="submit" class="btn btn-success">
|
<button type="submit" class="btn btn-success">
|
||||||
{% bootstrap_icon 'log-in' %} 
|
{% bootstrap_icon 'log-in' %} 
|
||||||
{% trans 'Login' %}
|
{% trans 'Login' %}
|
||||||
</button>
|
</button>
|
||||||
<a class="btn btn-danger" href="{% url 'dav_events:home' %}">
|
<a class="btn btn-danger" href="{% url 'root' %}">
|
||||||
{% bootstrap_icon 'remove' %} 
|
{% bootstrap_icon 'remove' %} 
|
||||||
{% trans 'Abbrechen' %}
|
{% trans 'Abbrechen' %}
|
||||||
</a>
|
</a>
|
||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
{% extends "dav_events/base.html" %}
|
{% extends "dav_auth/base.html" %}
|
||||||
{% load bootstrap3 %}
|
{% load bootstrap3 %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
{% bootstrap_icon 'saved' %} 
|
{% bootstrap_icon 'saved' %} 
|
||||||
{% trans 'Neues Passwort per E-Mail zusenden' %}
|
{% trans 'Neues Passwort per E-Mail zusenden' %}
|
||||||
</button>
|
</button>
|
||||||
<a class="btn btn-danger" href="{% url 'dav_events:home' %}">
|
<a class="btn btn-danger" href="{% url 'root' %}">
|
||||||
{% bootstrap_icon 'remove' %} 
|
{% bootstrap_icon 'remove' %} 
|
||||||
{% trans 'Abbrechen' %}
|
{% trans 'Abbrechen' %}
|
||||||
</a>
|
</a>
|
||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
{% extends "dav_events/base.html" %}
|
{% extends "dav_auth/base.html" %}
|
||||||
{% load bootstrap3 %}
|
{% load bootstrap3 %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
{% bootstrap_icon 'saved' %} 
|
{% bootstrap_icon 'saved' %} 
|
||||||
{% trans 'Neues Passwort setzen' %}
|
{% trans 'Neues Passwort setzen' %}
|
||||||
</button>
|
</button>
|
||||||
<a class="btn btn-danger" href="{% url 'dav_events:home' %}">
|
<a class="btn btn-danger" href="{% url 'root' %}">
|
||||||
{% bootstrap_icon 'remove' %} 
|
{% bootstrap_icon 'remove' %} 
|
||||||
{% trans 'Abbrechen' %}
|
{% trans 'Abbrechen' %}
|
||||||
</a>
|
</a>
|
||||||
+3
-3
@@ -7,12 +7,12 @@
|
|||||||
{{ user }} <span class="caret"></span>
|
{{ user }} <span class="caret"></span>
|
||||||
</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_events: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_events:logout' %}">{% trans 'Logout' %}</a></li>
|
<li><a href="{% url 'dav_auth:logout' %}">{% trans 'Logout' %}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<a class="btn btn-default btn-sm" href="{% url 'dav_events:login' %}">
|
<a class="btn btn-default btn-sm" href="{% url 'dav_auth:login' %}">
|
||||||
{% bootstrap_icon 'log-in' %}
|
{% bootstrap_icon 'log-in' %}
|
||||||
{% trans 'Login' %}
|
{% trans 'Login' %}
|
||||||
</a>
|
</a>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
from django.conf.urls import url
|
||||||
|
|
||||||
|
from . import views
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
url(r'^login$', views.LoginView.as_view(), name='login'),
|
||||||
|
url(r'^logout$', views.LogoutView.as_view(), name='logout'),
|
||||||
|
url(r'^password$', views.SetPasswordView.as_view(), name='set_password'),
|
||||||
|
url(r'^password/reset$', views.ResetPasswordView.as_view(), name='reset_password'),
|
||||||
|
]
|
||||||
@@ -1,24 +1,28 @@
|
|||||||
import logging
|
import logging
|
||||||
|
from django.apps import apps
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth import views as auth_views, get_user_model
|
from django.contrib.auth import views as auth_views, get_user_model
|
||||||
|
from django.shortcuts import resolve_url
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.views import generic
|
from django.views import generic
|
||||||
|
|
||||||
from .. import emails
|
from . import emails
|
||||||
from .. import forms
|
from . import forms
|
||||||
|
|
||||||
|
app_config = apps.get_containing_app_config(__package__)
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class LoginView(auth_views.LoginView):
|
class LoginView(auth_views.LoginView):
|
||||||
form_class = forms.auth.LoginForm
|
form_class = forms.LoginForm
|
||||||
next_page = reverse_lazy('dav_events:event_list')
|
template_name = 'dav_auth/forms/login.html'
|
||||||
template_name = 'dav_events/auth/login_form.html'
|
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_redirect_url(self):
|
||||||
url = self.get_redirect_url()
|
url = super(LoginView, self).get_redirect_url()
|
||||||
return url or self.next_page
|
if not url and app_config.settings.login_redirect_url:
|
||||||
|
url = resolve_url(app_config.settings.login_redirect_url)
|
||||||
|
return url
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
r = super(LoginView, self).form_valid(form)
|
r = super(LoginView, self).form_valid(form)
|
||||||
@@ -27,7 +31,11 @@ class LoginView(auth_views.LoginView):
|
|||||||
|
|
||||||
|
|
||||||
class LogoutView(auth_views.LogoutView):
|
class LogoutView(auth_views.LogoutView):
|
||||||
next_page = reverse_lazy('dav_events:home')
|
def get_next_page(self):
|
||||||
|
url = super(LogoutView, self).get_next_page()
|
||||||
|
if not url and app_config.settings.logout_redirect_url:
|
||||||
|
url = resolve_url(app_config.settings.logout_redirect_url)
|
||||||
|
return url
|
||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
r = super(LogoutView, self).dispatch(request, *args, **kwargs)
|
r = super(LogoutView, self).dispatch(request, *args, **kwargs)
|
||||||
@@ -36,9 +44,11 @@ class LogoutView(auth_views.LogoutView):
|
|||||||
|
|
||||||
|
|
||||||
class SetPasswordView(auth_views.PasswordChangeView):
|
class SetPasswordView(auth_views.PasswordChangeView):
|
||||||
form_class = forms.auth.SetPasswordForm
|
form_class = forms.SetPasswordForm
|
||||||
template_name = 'dav_events/auth/set_password_form.html'
|
template_name = 'dav_auth/forms/set_password.html'
|
||||||
success_url = reverse_lazy('dav_events:event_list')
|
|
||||||
|
def get_success_url(self):
|
||||||
|
return resolve_url(app_config.settings.login_redirect_url)
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
r = super(SetPasswordView, self).form_valid(form)
|
r = super(SetPasswordView, self).form_valid(form)
|
||||||
@@ -50,9 +60,9 @@ class SetPasswordView(auth_views.PasswordChangeView):
|
|||||||
|
|
||||||
|
|
||||||
class ResetPasswordView(generic.FormView):
|
class ResetPasswordView(generic.FormView):
|
||||||
form_class = forms.auth.ResetPasswordForm
|
form_class = forms.ResetPasswordForm
|
||||||
template_name = 'dav_events/auth/reset_password_form.html'
|
template_name = 'dav_auth/forms/reset_password.html'
|
||||||
success_url = reverse_lazy('dav_events:login')
|
success_url = reverse_lazy('dav_auth:login')
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
username = form.cleaned_data.get('username')
|
username = form.cleaned_data.get('username')
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
default_app_config = 'dav_base.apps.AppConfig'
|
||||||
File renamed without changes.
@@ -0,0 +1,13 @@
|
|||||||
|
from .config.apps import AppConfig as _AppConfig, DefaultSetting
|
||||||
|
|
||||||
|
DEFAULT_SETTINGS = (
|
||||||
|
DefaultSetting('email_sender', None),
|
||||||
|
DefaultSetting('email_base_url', None),
|
||||||
|
DefaultSetting('email_subject_prefix', ''),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class AppConfig(_AppConfig):
|
||||||
|
name = 'dav_base'
|
||||||
|
verbose_name = u'DAV Base App'
|
||||||
|
default_settings = DEFAULT_SETTINGS
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
from . import apps
|
||||||
|
from . import modules
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import importlib
|
||||||
|
import logging
|
||||||
|
import re
|
||||||
|
from django.apps import AppConfig as _AppConfig
|
||||||
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class DefaultSetting(object):
|
||||||
|
def __init__(self, name, value, key_name=None, validator=None):
|
||||||
|
self.name = name
|
||||||
|
self.value = value
|
||||||
|
if key_name is None:
|
||||||
|
self.key_name = self.name.upper()
|
||||||
|
else:
|
||||||
|
self.key_name = key_name
|
||||||
|
self.validator = validator
|
||||||
|
|
||||||
|
def validate(self, value):
|
||||||
|
if hasattr(self, 'validator') and self.validator is not None:
|
||||||
|
if callable(self.validator):
|
||||||
|
if not self.validator(value):
|
||||||
|
raise ImproperlyConfigured("Validator callback {clb} returned False".format(clb=self.validator))
|
||||||
|
else:
|
||||||
|
if not re.search(self.validator, value):
|
||||||
|
raise ImproperlyConfigured("Does not match /{re}/".format(re=self.validator))
|
||||||
|
|
||||||
|
|
||||||
|
class AppSettings(object):
|
||||||
|
def __init__(self, app_name, defaults):
|
||||||
|
settings_name = 'main.settings-' + app_name
|
||||||
|
|
||||||
|
try:
|
||||||
|
settings_module = importlib.import_module(settings_name)
|
||||||
|
except ImportError:
|
||||||
|
settings_module = None
|
||||||
|
|
||||||
|
for default in defaults:
|
||||||
|
if hasattr(settings_module, default.key_name):
|
||||||
|
value = getattr(settings_module, default.key_name)
|
||||||
|
try:
|
||||||
|
default.validate(value)
|
||||||
|
except ImproperlyConfigured as e:
|
||||||
|
msg = 'Invalid value of {key} in {module}: {cause}'.format(key=default.key_name,
|
||||||
|
module=settings_name,
|
||||||
|
cause=e.message)
|
||||||
|
raise ImproperlyConfigured(msg)
|
||||||
|
setattr(self, default.name, value)
|
||||||
|
elif isinstance(default.value, ImproperlyConfigured):
|
||||||
|
raise default.value
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
is_impconf = issubclass(default.value, ImproperlyConfigured)
|
||||||
|
except TypeError:
|
||||||
|
is_impconf = False
|
||||||
|
|
||||||
|
if is_impconf:
|
||||||
|
msg = '{key} must be defined in {module}'.format(key=default.key_name,
|
||||||
|
module=settings_name)
|
||||||
|
raise default.value(msg)
|
||||||
|
else:
|
||||||
|
setattr(self, default.name, default.value)
|
||||||
|
|
||||||
|
|
||||||
|
class AppConfig(_AppConfig):
|
||||||
|
default_settings = ()
|
||||||
|
|
||||||
|
def __init__(self, app_name, app_module):
|
||||||
|
super(AppConfig, self).__init__(app_name, app_module)
|
||||||
|
self.settings = AppSettings(app_name, self.default_settings)
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
import pkg_resources
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.conf.urls import url as django_conf_url, include
|
||||||
|
|
||||||
|
DJANGO_MAIN_MODULE = 'main'
|
||||||
|
MODULE_CONFIG_FILE_NAME = 'module_config.json'
|
||||||
|
|
||||||
|
|
||||||
|
class ModuleConfigError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ModuleMeta(object):
|
||||||
|
_json_file = 'module.json'
|
||||||
|
_root_url_name = 'root'
|
||||||
|
|
||||||
|
def __init__(self, package_name):
|
||||||
|
self._package_name = package_name
|
||||||
|
self._additional_apps = []
|
||||||
|
self._url_prefix = None
|
||||||
|
self._load_from_package()
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
t = '- {}'.format(self._package_name)
|
||||||
|
return t
|
||||||
|
|
||||||
|
@property
|
||||||
|
def app(self):
|
||||||
|
return self._package_name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def additional_apps(self):
|
||||||
|
return self._additional_apps
|
||||||
|
|
||||||
|
@property
|
||||||
|
def url_conf_pattern(self):
|
||||||
|
url_pattern = '^'
|
||||||
|
if self._url_prefix is None:
|
||||||
|
url_pattern += self._package_name
|
||||||
|
else:
|
||||||
|
url_pattern += self._url_prefix
|
||||||
|
url_pattern += '/'
|
||||||
|
url_conf = self._package_name + '.urls'
|
||||||
|
return django_conf_url(url_pattern, include(url_conf, self.url_namespace))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def url_namespace(self):
|
||||||
|
return self._package_name.replace('.', '_')
|
||||||
|
|
||||||
|
def _load_from_package(self):
|
||||||
|
package_name = self._package_name
|
||||||
|
json_text = pkg_resources.resource_string(package_name, self._json_file)
|
||||||
|
meta_dict = json.loads(json_text)
|
||||||
|
meta_dict['package'] = package_name
|
||||||
|
self.load_from_dict(meta_dict)
|
||||||
|
|
||||||
|
def load_from_dict(self, meta_dict):
|
||||||
|
self._package_name = meta_dict.get('package', None)
|
||||||
|
self._additional_apps = meta_dict.get('additional_apps', [])
|
||||||
|
self._url_prefix = meta_dict.get('url_prefix', None)
|
||||||
|
|
||||||
|
def dump_as_dict(self):
|
||||||
|
d = {
|
||||||
|
'package': self._package_name,
|
||||||
|
}
|
||||||
|
if self._additional_apps:
|
||||||
|
d['additional_apps'] = self._additional_apps
|
||||||
|
if self._url_prefix:
|
||||||
|
d['url_prefix'] = self._url_prefix
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
|
class ModuleConfig(object):
|
||||||
|
_lazy_load = True
|
||||||
|
|
||||||
|
def __init__(self, config_file_path=None, django_base_dir=None):
|
||||||
|
if config_file_path is None:
|
||||||
|
if django_base_dir is None:
|
||||||
|
django_base_dir = settings.BASE_DIR
|
||||||
|
config_file_path = os.path.join(django_base_dir, DJANGO_MAIN_MODULE, MODULE_CONFIG_FILE_NAME)
|
||||||
|
self._config_file_path = config_file_path
|
||||||
|
|
||||||
|
self._modules = dict()
|
||||||
|
|
||||||
|
self._loaded = False
|
||||||
|
if not self._lazy_load:
|
||||||
|
self._load()
|
||||||
|
|
||||||
|
def _lazy_init(self):
|
||||||
|
if not self._loaded:
|
||||||
|
self._load()
|
||||||
|
|
||||||
|
def _load(self):
|
||||||
|
path = self._config_file_path
|
||||||
|
|
||||||
|
self._modules = dict()
|
||||||
|
|
||||||
|
with open(path, 'r') as f:
|
||||||
|
data = json.load(f)
|
||||||
|
|
||||||
|
if 'modules' in data:
|
||||||
|
for meta_dict in data['modules']:
|
||||||
|
module_name = meta_dict['package']
|
||||||
|
self._modules[module_name] = ModuleMeta(module_name)
|
||||||
|
self._modules[module_name].load_from_dict(meta_dict)
|
||||||
|
|
||||||
|
self._loaded = True
|
||||||
|
|
||||||
|
@property
|
||||||
|
def modules(self):
|
||||||
|
self._lazy_init()
|
||||||
|
return self._modules
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
path = self._config_file_path
|
||||||
|
|
||||||
|
if os.path.exists(path):
|
||||||
|
self._lazy_init()
|
||||||
|
else:
|
||||||
|
self._loaded = True
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'modules': [],
|
||||||
|
}
|
||||||
|
for meta_obj in self._modules.values():
|
||||||
|
data['modules'].append(meta_obj.dump_as_dict())
|
||||||
|
|
||||||
|
with open(path, 'w') as f:
|
||||||
|
json.dump(data, f, indent=4)
|
||||||
Whitespace-only changes.
@@ -4,13 +4,15 @@ import pkg_resources
|
|||||||
import posix
|
import posix
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from dav_base.config.modules import DJANGO_MAIN_MODULE, ModuleConfig
|
||||||
|
|
||||||
VERSION = '0.1'
|
VERSION = '0.1'
|
||||||
|
|
||||||
|
|
||||||
class AdminCommand(object):
|
class AdminCommand(object):
|
||||||
def _setup_argparser(self):
|
def _setup_argparser(self):
|
||||||
kwargs = {
|
kwargs = {
|
||||||
'description': 'Tool to manage the DAV Events django project installation.',
|
'description': 'Tool to manage the DAV django project installation.',
|
||||||
'epilog': 'Off Belay.',
|
'epilog': 'Off Belay.',
|
||||||
}
|
}
|
||||||
parser = argparse.ArgumentParser(**kwargs)
|
parser = argparse.ArgumentParser(**kwargs)
|
||||||
@@ -36,30 +38,31 @@ class AdminCommand(object):
|
|||||||
return self._argparser.parse_args(argv)
|
return self._argparser.parse_args(argv)
|
||||||
|
|
||||||
def _subcmd_setup(self, cmd_args):
|
def _subcmd_setup(self, cmd_args):
|
||||||
django_project_name = 'main'
|
django_main_module = DJANGO_MAIN_MODULE
|
||||||
django_project_path = cmd_args.path
|
django_base_dir = cmd_args.path
|
||||||
|
|
||||||
sys.stdout.write('Setup installation in \'{path}\'...\n'.format(path=django_project_path))
|
sys.stdout.write('Setup installation in \'{path}\'...\n'.format(path=django_base_dir))
|
||||||
|
|
||||||
if os.path.exists(django_project_path):
|
if os.path.exists(django_base_dir):
|
||||||
if not os.path.isdir(django_project_path):
|
if not os.path.isdir(django_base_dir):
|
||||||
sys.stderr.write('{path}: Not a directory.\n'.format(path=django_project_path))
|
sys.stderr.write('{path}: Not a directory.\n'.format(path=django_base_dir))
|
||||||
return posix.EX_USAGE
|
return posix.EX_USAGE
|
||||||
else:
|
else:
|
||||||
os.makedirs(django_project_path)
|
os.makedirs(django_base_dir)
|
||||||
|
|
||||||
sys.stdout.write('Creating django project...\n')
|
sys.stdout.write('Creating django project...\n')
|
||||||
django_cmd = 'django-admin startproject {name} "{path}"'.format(name=django_project_name,
|
django_cmd = 'django-admin startproject {name} "{path}"'.format(name=django_main_module,
|
||||||
path=django_project_path)
|
path=django_base_dir)
|
||||||
exitval = os.system(django_cmd)
|
exitval = os.system(django_cmd)
|
||||||
if exitval != posix.EX_OK:
|
if exitval != posix.EX_OK:
|
||||||
return exitval
|
return exitval
|
||||||
|
|
||||||
sys.stdout.write('Creating directories...\n')
|
sys.stdout.write('Creating directories...\n')
|
||||||
dirs = [
|
dirs = [
|
||||||
os.path.join(django_project_path, 'var', 'db'),
|
os.path.join(django_base_dir, 'common', 'templates'),
|
||||||
os.path.join(django_project_path, 'var', 'log'),
|
os.path.join(django_base_dir, 'var', 'db'),
|
||||||
os.path.join(django_project_path, 'var', 'www', 'static'),
|
os.path.join(django_base_dir, 'var', 'log'),
|
||||||
|
os.path.join(django_base_dir, 'var', 'www', 'static'),
|
||||||
]
|
]
|
||||||
|
|
||||||
for d in dirs:
|
for d in dirs:
|
||||||
@@ -68,18 +71,21 @@ class AdminCommand(object):
|
|||||||
|
|
||||||
sys.stdout.write('Configure django project...\n')
|
sys.stdout.write('Configure django project...\n')
|
||||||
|
|
||||||
input_file = os.path.join('Resources', 'django.main.additional_settings.py')
|
config = ModuleConfig(django_base_dir=django_base_dir)
|
||||||
output_file = os.path.join(django_project_path, django_project_name, 'settings.py')
|
config.save()
|
||||||
|
|
||||||
|
input_file = os.path.join('django_project_config', 'additional_settings.py')
|
||||||
|
output_file = os.path.join(django_base_dir, django_main_module, 'settings.py')
|
||||||
with open(output_file, 'a') as f:
|
with open(output_file, 'a') as f:
|
||||||
f.write(pkg_resources.resource_string(__package__, input_file))
|
f.write(pkg_resources.resource_string(__package__, input_file))
|
||||||
|
|
||||||
input_file = os.path.join('Resources', 'django.main.urls.py')
|
input_file = os.path.join('django_project_config', 'urls.py')
|
||||||
output_file = os.path.join(django_project_path, django_project_name, 'urls.py')
|
output_file = os.path.join(django_base_dir, django_main_module, 'urls.py')
|
||||||
with open(output_file, 'w') as f:
|
with open(output_file, 'w') as f:
|
||||||
f.write(pkg_resources.resource_string(__package__, input_file))
|
f.write(pkg_resources.resource_string(__package__, input_file))
|
||||||
|
|
||||||
input_file = os.path.join('Resources', 'django.main.settings-dav_events.py')
|
input_file = os.path.join('django_project_config', 'settings-dav_base.py')
|
||||||
output_file = os.path.join(django_project_path, django_project_name, 'settings-dav_events.py')
|
output_file = os.path.join(django_base_dir, django_main_module, 'settings-dav_base.py')
|
||||||
with open(output_file, 'w') as f:
|
with open(output_file, 'w') as f:
|
||||||
f.write(pkg_resources.resource_string(__package__, input_file))
|
f.write(pkg_resources.resource_string(__package__, input_file))
|
||||||
|
|
||||||
+20
-3
@@ -1,20 +1,33 @@
|
|||||||
|
|
||||||
#
|
#
|
||||||
# Additional settings for django-dav-events
|
# Additional settings for django-dav
|
||||||
#
|
#
|
||||||
|
|
||||||
BASE_VAR_DIR = os.path.join(BASE_DIR, 'var')
|
BASE_VAR_DIR = os.path.join(BASE_DIR, 'var')
|
||||||
BASE_SHARE_DIR = os.path.join(BASE_DIR, 'common')
|
BASE_SHARE_DIR = os.path.join(BASE_DIR, 'common')
|
||||||
|
|
||||||
|
# Get modules config
|
||||||
|
from dav_base.config.modules import ModuleConfig
|
||||||
|
MODULE_CONFIG = ModuleConfig()
|
||||||
|
|
||||||
INSTALLED_APPS += [
|
INSTALLED_APPS += [
|
||||||
'bootstrap3',
|
'bootstrap3',
|
||||||
'datetimewidget',
|
'datetimewidget',
|
||||||
'django_countries',
|
'django_countries',
|
||||||
'django_extensions',
|
'django_extensions',
|
||||||
# Our main app
|
# Our main app
|
||||||
'dav_events',
|
'dav_base',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Add apps from our modules
|
||||||
|
for module_meta_obj in MODULE_CONFIG.modules.values():
|
||||||
|
if module_meta_obj.app:
|
||||||
|
INSTALLED_APPS.append(module_meta_obj.app)
|
||||||
|
if module_meta_obj.additional_apps:
|
||||||
|
for app in module_meta_obj.additional_apps:
|
||||||
|
INSTALLED_APPS.append(app)
|
||||||
|
|
||||||
|
# Add a template engine without html auto escape for rendering plain text templates.
|
||||||
TEMPLATES += [
|
TEMPLATES += [
|
||||||
{
|
{
|
||||||
'NAME': 'PLAINTEXT',
|
'NAME': 'PLAINTEXT',
|
||||||
@@ -30,6 +43,10 @@ TEMPLATES += [
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Add our local templates directory to the template engine configurations.
|
||||||
|
for config in TEMPLATES:
|
||||||
|
config['DIRS'].append(os.path.join(BASE_SHARE_DIR, 'templates'))
|
||||||
|
|
||||||
DATABASES['default'] = {
|
DATABASES['default'] = {
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
'NAME': os.path.join(BASE_VAR_DIR, 'db', 'devel.sqlite3'),
|
'NAME': os.path.join(BASE_VAR_DIR, 'db', 'devel.sqlite3'),
|
||||||
@@ -39,7 +56,7 @@ STATIC_ROOT = os.path.join(BASE_VAR_DIR, 'www', 'static')
|
|||||||
|
|
||||||
LANGUAGE_CODE = 'de'
|
LANGUAGE_CODE = 'de'
|
||||||
|
|
||||||
LOGIN_URL = 'dav_events:login'
|
LOGIN_URL = 'dav_auth:login'
|
||||||
|
|
||||||
BOOTSTRAP3 = {
|
BOOTSTRAP3 = {
|
||||||
'set_placeholder': False,
|
'set_placeholder': False,
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# E-Mails
|
||||||
|
EMAIL_SENDER = 'DAV heinzel <heinzel@alpenverein-karlsruhe.de>'
|
||||||
|
EMAIL_BASE_URL = 'http://localhost:8000'
|
||||||
|
EMAIL_SUBJECT_PREFIX = u'[DAV heinzel]'
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
from django.conf import settings
|
||||||
|
from django.conf.urls import url, include
|
||||||
|
|
||||||
|
urlpatterns = []
|
||||||
|
|
||||||
|
for module_meta_obj in settings.MODULE_CONFIG.modules.values():
|
||||||
|
if module_meta_obj.url_conf_pattern:
|
||||||
|
urlpatterns.append(module_meta_obj.url_conf_pattern)
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
url(r'^', include('dav_base.urls'))
|
||||||
|
]
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import logging
|
||||||
|
from django.apps import apps
|
||||||
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
from django.core.mail import EmailMessage
|
||||||
|
from django.template.loader import get_template
|
||||||
|
|
||||||
|
app_config = apps.get_containing_app_config(__package__)
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class AbstractMail(object):
|
||||||
|
_subject = u''
|
||||||
|
_template_name = None
|
||||||
|
|
||||||
|
def _get_sender(self):
|
||||||
|
#app_config = apps.get_containing_app_config(__package__)
|
||||||
|
return app_config.settings.email_sender
|
||||||
|
|
||||||
|
def _get_subject(self, subject_fmt=None, **kwargs):
|
||||||
|
if subject_fmt is None:
|
||||||
|
subject_fmt = self._subject
|
||||||
|
#app_config = apps.get_containing_app_config(__package__)
|
||||||
|
if app_config.settings.email_subject_prefix:
|
||||||
|
subject_fmt = u'%s %s' % (app_config.settings.email_subject_prefix, subject_fmt)
|
||||||
|
subject = subject_fmt.format(**kwargs)
|
||||||
|
return subject
|
||||||
|
|
||||||
|
def _get_template(self):
|
||||||
|
if not self._template_name:
|
||||||
|
raise ImproperlyConfigured('%s._template_name ist not set.', self.__class__.__name__)
|
||||||
|
return get_template(self._template_name, using='PLAINTEXT')
|
||||||
|
|
||||||
|
def _get_context_data(self, extra_context=None):
|
||||||
|
#app_config = apps.get_containing_app_config(__package__)
|
||||||
|
context = {
|
||||||
|
'base_url': app_config.settings.email_base_url,
|
||||||
|
}
|
||||||
|
if extra_context:
|
||||||
|
context.update(extra_context)
|
||||||
|
return context
|
||||||
|
|
||||||
|
def _get_body(self, context=None):
|
||||||
|
template = self._get_template()
|
||||||
|
context = self._get_context_data(extra_context=context)
|
||||||
|
return template.render(context)
|
||||||
|
|
||||||
|
def _get_recipients(self):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def send(self):
|
||||||
|
subject = self._get_subject()
|
||||||
|
body = self._get_body()
|
||||||
|
sender = self._get_sender()
|
||||||
|
recipients = self._get_recipients()
|
||||||
|
|
||||||
|
email = EmailMessage(subject=subject, body=body, from_email=sender, to=recipients)
|
||||||
|
logger.info(u'Send %s to %s', self.__class__.__name__, recipients)
|
||||||
|
email.send()
|
||||||
Whitespace-only changes.
Whitespace-only changes.
@@ -0,0 +1,18 @@
|
|||||||
|
from django.conf import settings
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = 'Disable a modular app from django-dav installation.'
|
||||||
|
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument('module')
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
module_name = options['module']
|
||||||
|
|
||||||
|
config = settings.MODULE_CONFIG
|
||||||
|
del config.modules[module_name]
|
||||||
|
config.save()
|
||||||
|
|
||||||
|
self.stdout.write(self.style.SUCCESS('Module \'{}\' disabled.'.format(module_name)))
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import os
|
||||||
|
import pkg_resources
|
||||||
|
from django.conf import settings
|
||||||
|
from django.core.management.base import BaseCommand, CommandError
|
||||||
|
|
||||||
|
from dav_base.config.modules import DJANGO_MAIN_MODULE, ModuleMeta
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = 'Enable a modular app in django-dav installation.'
|
||||||
|
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument('module', help='the name of the module')
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
django_base_dir = settings.BASE_DIR
|
||||||
|
django_main_module = DJANGO_MAIN_MODULE
|
||||||
|
module_name = options['module']
|
||||||
|
|
||||||
|
config = settings.MODULE_CONFIG
|
||||||
|
|
||||||
|
if module_name in config.modules.keys():
|
||||||
|
raise CommandError('Module \'{}\' is already enabled'.format(module_name))
|
||||||
|
|
||||||
|
settings_file_name = 'settings-{}.py'.format(module_name)
|
||||||
|
input_file = os.path.join('django_project_config', settings_file_name)
|
||||||
|
if pkg_resources.resource_exists(module_name, input_file):
|
||||||
|
output_file = os.path.join(django_base_dir, django_main_module, settings_file_name)
|
||||||
|
if not os.path.exists(output_file):
|
||||||
|
with open(output_file, 'w') as f:
|
||||||
|
f.write(pkg_resources.resource_string(module_name, input_file))
|
||||||
|
|
||||||
|
module_meta_obj = ModuleMeta(module_name)
|
||||||
|
config.modules[module_name] = module_meta_obj
|
||||||
|
config.save()
|
||||||
|
|
||||||
|
self.stdout.write(self.style.SUCCESS('Module \'{}\' enabled.'.format(module_name)))
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
from django.conf import settings
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = 'List enabled modular apps in django-dav installation.'
|
||||||
|
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
paragraphs = []
|
||||||
|
config = settings.MODULE_CONFIG
|
||||||
|
for obj in config.modules.values():
|
||||||
|
paragraphs.append(str(obj))
|
||||||
|
output = '\n'.join(paragraphs)
|
||||||
|
self.stdout.write(output)
|
||||||
Whitespace-only changes.
Whitespace-only changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,4 +1,4 @@
|
|||||||
{% extends "error_base.html" %}
|
{% extends "dav_base/error_base.html" %}
|
||||||
|
|
||||||
{% block error-code %}400{% endblock %}
|
{% block error-code %}400{% endblock %}
|
||||||
{% block error-title %}Bad Request{% endblock %}
|
{% block error-title %}Bad Request{% endblock %}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
{% extends "error_base.html" %}
|
{% extends "dav_base/error_base.html" %}
|
||||||
|
|
||||||
{% block error-code %}403{% endblock %}
|
{% block error-code %}403{% endblock %}
|
||||||
{% block error-title %}Forbidden{% endblock %}
|
{% block error-title %}Forbidden{% endblock %}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
{% extends "error_base.html" %}
|
{% extends "dav_base/error_base.html" %}
|
||||||
|
|
||||||
{% block error-code %}404{% endblock %}
|
{% block error-code %}404{% endblock %}
|
||||||
{% block error-title %}Not Found{% endblock %}
|
{% block error-title %}Not Found{% endblock %}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
{% extends "error_base.html" %}
|
{% extends "dav_base/error_base.html" %}
|
||||||
|
|
||||||
{% block error-code %}500{% endblock %}
|
{% block error-code %}500{% endblock %}
|
||||||
{% block error-title %}Internal Server Error{% endblock %}
|
{% block error-title %}Internal Server Error{% endblock %}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
{% load static %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load bootstrap3 %}
|
||||||
|
{% load dav_base %}
|
||||||
|
<html lang="{{ LANGUAGE_CODE|default:'de' }}">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
|
||||||
|
{% block head-media %}
|
||||||
|
<link type="image/x-icon" href="{% static 'dav_base/img/dav-favicon.ico' %}" rel="shortcut icon" />
|
||||||
|
<link type="text/css" href="{% static 'dav_base/bootstrap/css/bootstrap.min.css' %}" rel="stylesheet" />
|
||||||
|
<link type="text/css" href="{% static 'dav_base/css/dataTables.bootstrap.min.css' %}" rel="stylesheet" />
|
||||||
|
<link type="text/css" href="{% static 'dav_base/css/local.css' %}" rel="stylesheet" />
|
||||||
|
|
||||||
|
<script type="text/javascript" src="{% static 'dav_base/js/jquery.min.js' %}"></script>
|
||||||
|
<script type="text/javascript" src="{% static 'dav_base/js/jquery.dataTables.min.js' %}"></script>
|
||||||
|
<script type="text/javascript" src="{% static 'dav_base/bootstrap/js/bootstrap.min.js' %}"></script>
|
||||||
|
|
||||||
|
{{ form.media }}
|
||||||
|
{% endblock head-media %}
|
||||||
|
|
||||||
|
{% block head-additional %}
|
||||||
|
{% endblock head-additional %}
|
||||||
|
|
||||||
|
<title>
|
||||||
|
{% block head-title %}Alpenverein Karlsruhe{% endblock head-title %}
|
||||||
|
</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="page">
|
||||||
|
<div id="page-header">
|
||||||
|
<h2>
|
||||||
|
<a href="{% url 'root' %}">
|
||||||
|
<img width="217" height="30" src="{% static 'dav_base/img/brand.png' %}" />{% block project-name %}{% include_if_exist 'project_name.html' %}{% endblock project-name %}
|
||||||
|
</a>
|
||||||
|
</h2>
|
||||||
|
<div id="login-widget">{% include_if_exist 'dav_auth/includes/login_widget.html' %}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="messages">
|
||||||
|
{% block messages %}
|
||||||
|
<div class="container-fluid">
|
||||||
|
{% bootstrap_messages %}
|
||||||
|
</div>
|
||||||
|
{% endblock messages %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="page-body">
|
||||||
|
{% block modals %}
|
||||||
|
{% endblock modals %}
|
||||||
|
{% block page-body %}
|
||||||
|
<div class="container-fluid">
|
||||||
|
{% block page-container-fluid %}
|
||||||
|
{% endblock page-container-fluid %}
|
||||||
|
</div>
|
||||||
|
<div class="container">
|
||||||
|
{% block page-container %}
|
||||||
|
{% endblock page-container %}
|
||||||
|
</div>
|
||||||
|
{% endblock page-body %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="page-footer">
|
||||||
|
<div class="signum">{% block signum %}<a href="mailto:heinzel@alpenverein-karlsruhe.de">heinzel@alpenverein-karlsruhe.de</a>{% endblock signum %}</div>
|
||||||
|
<a href="http://alpenverein-karlsruhe.de" target="_blank">© Sektion Karlsruhe im Deutschen Alpenverein (DAV) e.V.</a>  • 
|
||||||
|
<a href="http://alpenverein-karlsruhe.de/impressum">{% trans 'Impressum' %}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
{% extends "dav_events/base.html" %}
|
{% extends "dav_base/base.html" %}
|
||||||
{% load bootstrap3 %}
|
{% load bootstrap3 %}
|
||||||
|
|
||||||
{% block head-title %}{% block error-code %}{% endblock %} {% block error-title %}Error{% endblock %} - {{ block.super }}{% endblock head-title %}
|
{% block head-title %}{% block error-code %}{% endblock %} {% block error-title %}Error{% endblock %} - {{ block.super }}{% endblock head-title %}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
{% extends "dav_base/base.html" %}
|
||||||
|
{% load bootstrap3 %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block page-container %}
|
||||||
|
<div class="jumbotron">
|
||||||
|
<h1>Hallo,</h1>
|
||||||
|
<p>
|
||||||
|
du bist auf dem Entwicklungs- und Testserver der
|
||||||
|
<a href="http://alpenverein-karlsruhe.de">Sektion Karlsruhe des Deutschen Alpenvereins (DAV) e.V.</a> gelandet.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Wenn du Fragen hast, kannst du dich an
|
||||||
|
<a href="mailto:heinzel@alpenverein-karlsruhe.de">heinzel@alpenverein-karlsruhe.de</a> wenden.
|
||||||
|
</p>
|
||||||
|
<p> </p>
|
||||||
|
{% if root_urls %}
|
||||||
|
<h3>Module:</h3>
|
||||||
|
<div class="list-group">
|
||||||
|
{% for root_url in root_urls %}
|
||||||
|
<a class="list-group-item list-group-item-warning"
|
||||||
|
href="{% url root_url.1 %}"><span class="glyphicon glyphicon-arrow-right"></span> {{ root_url.0 }}</a>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endblock page-container %}
|
||||||
Whitespace-only changes.
Whitespace-only changes.
@@ -0,0 +1,53 @@
|
|||||||
|
from django import template
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
|
@register.tag('include_if_exist')
|
||||||
|
def do_include_if_exist(parser, token):
|
||||||
|
"""
|
||||||
|
Used to include a template, that maybe does not exist.
|
||||||
|
|
||||||
|
include_if_exist support an optional keyword 'default', which must be followed by the name of a default template.
|
||||||
|
The default template will be included, if the first template does not exist.
|
||||||
|
If also the default template does not exist, the behaviour is the same as for the original (builtin) include tag.
|
||||||
|
|
||||||
|
If no default template is given and the first template does not exist an empty string will be returned.
|
||||||
|
"""
|
||||||
|
bits = token.split_contents()
|
||||||
|
if len(bits) < 2:
|
||||||
|
raise template.TemplateSyntaxError("%r tag takes at least two arguments:"
|
||||||
|
" the name of the template to be included" % bits[0])
|
||||||
|
|
||||||
|
try:
|
||||||
|
pos = bits.index('default')
|
||||||
|
del bits[pos]
|
||||||
|
default_template = bits[pos]
|
||||||
|
del bits[pos]
|
||||||
|
token = template.base.Token(token.token_type, ' '.join(bits))
|
||||||
|
token2 = template.base.Token(token.token_type, bits[0] + ' ' + default_template + ' '.join(bits[2:]))
|
||||||
|
default_node = template.loader_tags.do_include(parser, token2)
|
||||||
|
except ValueError:
|
||||||
|
default_node = template.defaulttags.CommentNode()
|
||||||
|
except IndexError:
|
||||||
|
raise template.TemplateSyntaxError("'default' keyword in %r tag requires another arguments:"
|
||||||
|
" the name of the default template" % bits[0])
|
||||||
|
|
||||||
|
try:
|
||||||
|
include_node = template.loader_tags.do_include(parser, token)
|
||||||
|
except template.TemplateDoesNotExist:
|
||||||
|
return default_node
|
||||||
|
|
||||||
|
orig_render = include_node.render
|
||||||
|
orig_template = include_node.template
|
||||||
|
|
||||||
|
def wrapped_render(context, *args, **kwargs):
|
||||||
|
try:
|
||||||
|
t = orig_template.resolve(context)
|
||||||
|
if not callable(getattr(t, 'render', None)):
|
||||||
|
t = context.template.engine.find_template(t)
|
||||||
|
return orig_render(context, *args, **kwargs)
|
||||||
|
except template.TemplateDoesNotExist:
|
||||||
|
return default_node.render(context, *args, **kwargs)
|
||||||
|
include_node.render = wrapped_render
|
||||||
|
return include_node
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
from django.conf.urls import url
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
from . import views
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
url(r'^$', views.RootView.as_view(), name='root'),
|
||||||
|
url(r'^djangoadmin/', admin.site.urls),
|
||||||
|
]
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
from django.conf import settings
|
||||||
|
from django.urls import reverse, NoReverseMatch
|
||||||
|
from django.views import generic
|
||||||
|
|
||||||
|
|
||||||
|
class RootView(generic.TemplateView):
|
||||||
|
template_name = 'dav_base/root.html'
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
c = super(RootView, self).get_context_data(**kwargs)
|
||||||
|
root_urls = []
|
||||||
|
for module_meta_obj in settings.MODULE_CONFIG.modules.values():
|
||||||
|
root_url_name = 'root'
|
||||||
|
if module_meta_obj.url_namespace:
|
||||||
|
root_url_name = '%s:%s' % (module_meta_obj.url_namespace, root_url_name)
|
||||||
|
try:
|
||||||
|
reverse(root_url_name)
|
||||||
|
root_urls.append((module_meta_obj.app, root_url_name))
|
||||||
|
except NoReverseMatch:
|
||||||
|
pass
|
||||||
|
|
||||||
|
c['root_urls'] = root_urls
|
||||||
|
return c
|
||||||
+2
-4
@@ -1,13 +1,11 @@
|
|||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
|
||||||
|
from dav_base.config.apps import AppConfig as _AppConfig, DefaultSetting
|
||||||
|
|
||||||
from . import signals
|
from . import signals
|
||||||
from .config import AppConfig as _AppConfig, DefaultSetting
|
|
||||||
|
|
||||||
DEFAULT_SETTINGS = (
|
DEFAULT_SETTINGS = (
|
||||||
DefaultSetting('enable_email_notifications', False),
|
DefaultSetting('enable_email_notifications', False),
|
||||||
DefaultSetting('email_sender', None),
|
|
||||||
DefaultSetting('email_base_url', None),
|
|
||||||
DefaultSetting('email_subject_prefix', ''),
|
|
||||||
DefaultSetting('group_manage_all', None),
|
DefaultSetting('group_manage_all', None),
|
||||||
DefaultSetting('group_manage_w', None),
|
DefaultSetting('group_manage_w', None),
|
||||||
DefaultSetting('group_manage_s', None),
|
DefaultSetting('group_manage_s', None),
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
import importlib
|
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
from django.apps import AppConfig as _AppConfig
|
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -84,67 +81,3 @@ class FieldInitial(object):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
class DefaultSetting(object):
|
|
||||||
def __init__(self, name, value, key_name=None, validator=None):
|
|
||||||
self.name = name
|
|
||||||
self.value = value
|
|
||||||
if key_name is None:
|
|
||||||
self.key_name = self.name.upper()
|
|
||||||
else:
|
|
||||||
self.key_name = key_name
|
|
||||||
self.validator = validator
|
|
||||||
|
|
||||||
def validate(self, value):
|
|
||||||
if hasattr(self, 'validator') and self.validator is not None:
|
|
||||||
if callable(self.validator):
|
|
||||||
if not self.validator(value):
|
|
||||||
raise ImproperlyConfigured("Validator callback {clb} returned False".format(clb=self.validator))
|
|
||||||
else:
|
|
||||||
if not re.search(self.validator, value):
|
|
||||||
raise ImproperlyConfigured("Does not match /{re}/".format(re=self.validator))
|
|
||||||
|
|
||||||
|
|
||||||
class AppSettings(object):
|
|
||||||
def __init__(self, app_name, defaults):
|
|
||||||
settings_name = 'main.settings-' + app_name
|
|
||||||
|
|
||||||
try:
|
|
||||||
settings_module = importlib.import_module(settings_name)
|
|
||||||
except ImportError:
|
|
||||||
settings_module = None
|
|
||||||
|
|
||||||
for default in defaults:
|
|
||||||
if hasattr(settings_module, default.key_name):
|
|
||||||
value = getattr(settings_module, default.key_name)
|
|
||||||
try:
|
|
||||||
default.validate(value)
|
|
||||||
except ImproperlyConfigured as e:
|
|
||||||
msg = 'Invalid value of {key} in {module}: {cause}'.format(key=default.key_name,
|
|
||||||
module=settings_name,
|
|
||||||
cause=e.message)
|
|
||||||
raise ImproperlyConfigured(msg)
|
|
||||||
setattr(self, default.name, value)
|
|
||||||
elif isinstance(default.value, ImproperlyConfigured):
|
|
||||||
raise default.value
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
is_impconf = issubclass(default.value, ImproperlyConfigured)
|
|
||||||
except TypeError:
|
|
||||||
is_impconf = False
|
|
||||||
|
|
||||||
if is_impconf:
|
|
||||||
msg = '{key} must be defined in {module}'.format(key=default.key_name,
|
|
||||||
module=settings_name)
|
|
||||||
raise default.value(msg)
|
|
||||||
else:
|
|
||||||
setattr(self, default.name, default.value)
|
|
||||||
|
|
||||||
|
|
||||||
class AppConfig(_AppConfig):
|
|
||||||
default_settings = ()
|
|
||||||
|
|
||||||
def __init__(self, app_name, app_module):
|
|
||||||
super(AppConfig, self).__init__(app_name, app_module)
|
|
||||||
self.settings = AppSettings(app_name, self.default_settings)
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
from django.conf.urls import url, include
|
|
||||||
from django.contrib import admin
|
|
||||||
|
|
||||||
urlpatterns = [
|
|
||||||
url(r'^', include('dav_events.urls', namespace='dav_events')),
|
|
||||||
url(r'^admin/', admin.site.urls),
|
|
||||||
]
|
|
||||||
-3
@@ -4,9 +4,6 @@ from dav_events.config import FieldInitial
|
|||||||
|
|
||||||
# E-Mails
|
# E-Mails
|
||||||
ENABLE_EMAIL_NOTIFICATIONS = False
|
ENABLE_EMAIL_NOTIFICATIONS = False
|
||||||
EMAIL_SENDER = 'DAV Veranstaltungsheinzel <heinzel@alpenverein-karlsruhe.de>'
|
|
||||||
EMAIL_BASE_URL = 'http://localhost:8000'
|
|
||||||
EMAIL_SUBJECT_PREFIX = u'[DAV Veranstaltungen]'
|
|
||||||
|
|
||||||
# Authorization Roles / Groups
|
# Authorization Roles / Groups
|
||||||
GROUP_MANAGE_ALL = 'Tourenreferenten'
|
GROUP_MANAGE_ALL = 'Tourenreferenten'
|
||||||
+1
-80
@@ -1,61 +1,5 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import logging
|
from dav_base.emails import AbstractMail
|
||||||
from django.apps import apps
|
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
|
||||||
from django.core.mail import EmailMessage
|
|
||||||
from django.template.loader import get_template
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class AbstractMail(object):
|
|
||||||
_subject = u''
|
|
||||||
_template_name = None
|
|
||||||
|
|
||||||
def _get_sender(self):
|
|
||||||
app_config = apps.get_containing_app_config(__package__)
|
|
||||||
return app_config.settings.email_sender
|
|
||||||
|
|
||||||
def _get_subject(self, subject_fmt=None, **kwargs):
|
|
||||||
if subject_fmt is None:
|
|
||||||
subject_fmt = self._subject
|
|
||||||
app_config = apps.get_containing_app_config(__package__)
|
|
||||||
if app_config.settings.email_subject_prefix:
|
|
||||||
subject_fmt = u'%s %s' % (app_config.settings.email_subject_prefix, subject_fmt)
|
|
||||||
subject = subject_fmt.format(**kwargs)
|
|
||||||
return subject
|
|
||||||
|
|
||||||
def _get_template(self):
|
|
||||||
if not self._template_name:
|
|
||||||
raise ImproperlyConfigured('%s._template_name ist not set.', self.__class__.__name__)
|
|
||||||
return get_template(self._template_name, using='PLAINTEXT')
|
|
||||||
|
|
||||||
def _get_context_data(self, extra_context=None):
|
|
||||||
app_config = apps.get_containing_app_config(__package__)
|
|
||||||
context = {
|
|
||||||
'base_url': app_config.settings.email_base_url,
|
|
||||||
}
|
|
||||||
if extra_context:
|
|
||||||
context.update(extra_context)
|
|
||||||
return context
|
|
||||||
|
|
||||||
def _get_body(self, context=None):
|
|
||||||
template = self._get_template()
|
|
||||||
context = self._get_context_data(extra_context=context)
|
|
||||||
return template.render(context)
|
|
||||||
|
|
||||||
def _get_recipients(self):
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
def send(self):
|
|
||||||
subject = self._get_subject()
|
|
||||||
body = self._get_body()
|
|
||||||
sender = self._get_sender()
|
|
||||||
recipients = self._get_recipients()
|
|
||||||
|
|
||||||
emo = EmailMessage(subject=subject, body=body, from_email=sender, to=recipients)
|
|
||||||
logger.info(u'Send %s to %s', self.__class__.__name__, recipients)
|
|
||||||
emo.send()
|
|
||||||
|
|
||||||
|
|
||||||
class AbstractEventMail(AbstractMail):
|
class AbstractEventMail(AbstractMail):
|
||||||
@@ -149,26 +93,3 @@ class EventToPublishMail(AbstractEventMail):
|
|||||||
context['editor'] = self._editor
|
context['editor'] = self._editor
|
||||||
context['confirm_publication_url'] = self._confirm_publication_action.get_absolute_url()
|
context['confirm_publication_url'] = self._confirm_publication_action.get_absolute_url()
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class PasswordSetEmail(AbstractMail):
|
|
||||||
_subject = u'Zugangsdaten'
|
|
||||||
_template_name = 'dav_events/emails/password_set.txt'
|
|
||||||
|
|
||||||
def __init__(self, user, password):
|
|
||||||
self._user = user
|
|
||||||
self._password = password
|
|
||||||
|
|
||||||
def _get_recipients(self):
|
|
||||||
r = u'{fullname} <{email}>'.format(fullname=self._user.get_full_name(),
|
|
||||||
email=self._user.email)
|
|
||||||
return [r]
|
|
||||||
|
|
||||||
def _get_context_data(self, extra_context=None):
|
|
||||||
context = super(PasswordSetEmail, self)._get_context_data(extra_context=extra_context)
|
|
||||||
context.update({
|
|
||||||
'fullname': self._user.get_full_name(),
|
|
||||||
'username': self._user.username,
|
|
||||||
'password': self._password
|
|
||||||
})
|
|
||||||
return context
|
|
||||||
@@ -1,3 +1,2 @@
|
|||||||
from . import generic
|
from . import generic
|
||||||
from . import auth
|
|
||||||
from . import events
|
from . import events
|
||||||
@@ -254,7 +254,7 @@ class Event(models.Model):
|
|||||||
date=self.get_formated_date())
|
date=self.get_formated_date())
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse('dav_events:event_detail', kwargs={'pk': self.pk})
|
return reverse('dav_events:detail', kwargs={'pk': self.pk})
|
||||||
|
|
||||||
def save(self, implicit_update=False, **kwargs):
|
def save(self, implicit_update=False, **kwargs):
|
||||||
creating = False
|
creating = False
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ class OneClickAction(models.Model):
|
|||||||
try:
|
try:
|
||||||
user_id = self.parameters
|
user_id = self.parameters
|
||||||
user = get_user_model().objects.get(id=user_id)
|
user = get_user_model().objects.get(id=user_id)
|
||||||
url = reverse('dav_events:event_list')
|
url = reverse('dav_events:list')
|
||||||
result['location'] = url
|
result['location'] = url
|
||||||
result['login'] = user
|
result['login'] = user
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"url_prefix": "events"
|
||||||
|
}
|
||||||
@@ -1,71 +1,3 @@
|
|||||||
<!DOCTYPE html>
|
{% extends "dav_base/base.html" %}
|
||||||
{% load static %}
|
|
||||||
{% load i18n %}
|
|
||||||
{% load bootstrap3 %}
|
|
||||||
<html lang="{{ LANGUAGE_CODE|default:'de' }}">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
|
|
||||||
{% block head-media %}
|
{% block head-title %}Touren und Kurse - {{ block.super }}{% endblock %}
|
||||||
<link type="image/x-icon" href="{% static 'dav_events/img/dav-favicon.ico' %}" rel="shortcut icon" />
|
|
||||||
<link type="text/css" href="{% static 'dav_events/bootstrap/css/bootstrap.min.css' %}" rel="stylesheet" />
|
|
||||||
<link type="text/css" href="{% static 'dav_events/css/dataTables.bootstrap.min.css' %}" rel="stylesheet" />
|
|
||||||
<link type="text/css" href="{% static 'dav_events/css/local.css' %}" rel="stylesheet" />
|
|
||||||
|
|
||||||
<script type="text/javascript" src="{% static 'dav_events/js/jquery.min.js' %}"></script>
|
|
||||||
<script type="text/javascript" src="{% static 'dav_events/js/jquery.dataTables.min.js' %}"></script>
|
|
||||||
<script type="text/javascript" src="{% static 'dav_events/bootstrap/js/bootstrap.min.js' %}"></script>
|
|
||||||
|
|
||||||
{{ form.media }}
|
|
||||||
{% endblock head-media %}
|
|
||||||
|
|
||||||
{% block head-additional %}
|
|
||||||
{% endblock head-additional %}
|
|
||||||
|
|
||||||
<title>
|
|
||||||
{% block head-title %}Veranstaltungsheinzel - Alpenverein Karlsruhe{% endblock head-title %}
|
|
||||||
</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="page">
|
|
||||||
<div id="page-header">
|
|
||||||
<h2>
|
|
||||||
<a href="{% url 'dav_events:home' %}">
|
|
||||||
<img width="217" height="30" src="{% static 'dav_events/img/brand.png' %}" />Veranstaltungsheinzel
|
|
||||||
</a>
|
|
||||||
</h2>
|
|
||||||
<div id="login-widget">{% include 'dav_events/includes/login_widget.html' %}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="messages">
|
|
||||||
{% block messages %}
|
|
||||||
<div class="container-fluid">
|
|
||||||
{% bootstrap_messages %}
|
|
||||||
</div>
|
|
||||||
{% endblock messages %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="page-body">
|
|
||||||
{% block modals %}
|
|
||||||
{% endblock modals %}
|
|
||||||
{% block page-body %}
|
|
||||||
<div class="container-fluid">
|
|
||||||
{% block page-container-fluid %}
|
|
||||||
{% endblock page-container-fluid %}
|
|
||||||
</div>
|
|
||||||
<div class="container">
|
|
||||||
{% block page-container %}
|
|
||||||
{% endblock page-container %}
|
|
||||||
</div>
|
|
||||||
{% endblock page-body %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="page-footer">
|
|
||||||
<div class="signum"><a href="mailto:heinzel@alpenverein-karlsruhe.de">heinzel@alpenverein-karlsruhe.de</a></div>
|
|
||||||
<a href="http://alpenverein-karlsruhe.de" target="_blank">© Sektion Karlsruhe im Deutschen Alpenverein (DAV) e.V.</a>  • 
|
|
||||||
<a href="http://alpenverein-karlsruhe.de/impressum">{% trans 'Impressum' %}</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<a class="btn btn-success" href="{% url 'dav_events:event_confirmstatus' event.pk 'submitted' %}">
|
<a class="btn btn-success" href="{% url 'dav_events:confirmstatus' event.pk 'submitted' %}">
|
||||||
{% bootstrap_icon 'ok' %} 
|
{% bootstrap_icon 'ok' %} 
|
||||||
{% trans 'Ja, alles klar!' %}
|
{% trans 'Ja, alles klar!' %}
|
||||||
</a>
|
</a>
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<a class="btn btn-success" href="{% url 'dav_events:event_confirmstatus' event.pk 'accepted' %}">
|
<a class="btn btn-success" href="{% url 'dav_events:confirmstatus' event.pk 'accepted' %}">
|
||||||
{% bootstrap_icon 'ok' %} 
|
{% bootstrap_icon 'ok' %} 
|
||||||
{% trans 'Ja, passt schon!' %}
|
{% trans 'Ja, passt schon!' %}
|
||||||
</a>
|
</a>
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<a class="btn btn-success" href="{% if event.planned_publication_date %}{% url 'dav_events:event_confirmstatus' event.pk 'publishing' %}{% else %}{% url 'dav_events:event_confirmstatus' event.pk 'published' %}{% endif %}">
|
<a class="btn btn-success" href="{% if event.planned_publication_date %}{% url 'dav_events:confirmstatus' event.pk 'publishing' %}{% else %}{% url 'dav_events:confirmstatus' event.pk 'published' %}{% endif %}">
|
||||||
{% bootstrap_icon 'ok' %} 
|
{% bootstrap_icon 'ok' %} 
|
||||||
{% trans 'Ja' %}
|
{% trans 'Ja' %}
|
||||||
</a>
|
</a>
|
||||||
@@ -135,7 +135,7 @@
|
|||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a class="btn btn-primary"
|
<a class="btn btn-primary"
|
||||||
href="{% url 'dav_events:event_create' %}?copy={{ event.pk }}"
|
href="{% url 'dav_events:create' %}?copy={{ event.pk }}"
|
||||||
title="{% trans 'Diese Veranstaltung als Vorlage für eine neue Veranstaltung benutzen' %}">
|
title="{% trans 'Diese Veranstaltung als Vorlage für eine neue Veranstaltung benutzen' %}">
|
||||||
{% bootstrap_icon 'duplicate' %} 
|
{% bootstrap_icon 'duplicate' %} 
|
||||||
{% trans 'Kopieren' %}
|
{% trans 'Kopieren' %}
|
||||||
@@ -144,15 +144,15 @@
|
|||||||
<ul class="nav nav-tabs" role="tablist">
|
<ul class="nav nav-tabs" role="tablist">
|
||||||
<li>
|
<li>
|
||||||
<a class="btn"
|
<a class="btn"
|
||||||
href="{% url 'dav_events:event_list' %}">{% trans 'Veranstaltungsliste' %}</a>
|
href="{% url 'dav_events:list' %}">{% trans 'Veranstaltungsliste' %}</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="active">
|
<li class="active">
|
||||||
<a class="btn"
|
<a class="btn"
|
||||||
href="{% url 'dav_events:event_detail' event.pk %}">{% trans 'Details' %}</a>
|
href="{% url 'dav_events:detail' event.pk %}">{% trans 'Details' %}</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="{% if not has_permission_update %}disabled{% endif %}">
|
<li class="{% if not has_permission_update %}disabled{% endif %}">
|
||||||
<a class="btn {% if has_permission_update %}btn-warning{% else %}disabled{% endif %}"
|
<a class="btn {% if has_permission_update %}btn-warning{% else %}disabled{% endif %}"
|
||||||
href="{% url 'dav_events:event_update' event.pk %}">{% trans 'Ändern' %}</a>
|
href="{% url 'dav_events:update' event.pk %}">{% trans 'Ändern' %}</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,18 +6,18 @@
|
|||||||
<div class="action-tabs">
|
<div class="action-tabs">
|
||||||
<div class="pull-right">
|
<div class="pull-right">
|
||||||
<a class="btn btn-primary"
|
<a class="btn btn-primary"
|
||||||
href="{% url 'dav_events:event_create' %}">
|
href="{% url 'dav_events:create' %}">
|
||||||
{% bootstrap_icon 'plus' %}
|
{% bootstrap_icon 'plus' %}
|
||||||
{% trans 'Neue Veranstaltung anlegen' %}
|
{% trans 'Neue Veranstaltung anlegen' %}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<ul class="nav nav-tabs" role="tablist">
|
<ul class="nav nav-tabs" role="tablist">
|
||||||
<li class="active">
|
<li class="active">
|
||||||
<a href="{% url 'dav_events:event_list' %}">{% trans 'Veranstaltungsliste' %}</a>
|
<a href="{% url 'dav_events:list' %}">{% trans 'Veranstaltungsliste' %}</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="{% if not has_permission_export %}disabled{% endif %}">
|
<li class="{% if not has_permission_export %}disabled{% endif %}">
|
||||||
<a class="btn {% if not has_permission_export %}disabled{% endif %}"
|
<a class="btn {% if not has_permission_export %}disabled{% endif %}"
|
||||||
href="{% url 'dav_events:event_list_export' %}">{% trans 'Veranstaltungsliste herunterladen' %}</a>
|
href="{% url 'dav_events:list_export' %}">{% trans 'Veranstaltungsliste herunterladen' %}</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -45,11 +45,11 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td data-order="{{ event.get_number|slice:':1' }}{{ event.get_number|slice:'-2:' }}{{ event.get_number|slice:'1:-2'|cut:'/' }}"
|
<td data-order="{{ event.get_number|slice:':1' }}{{ event.get_number|slice:'-2:' }}{{ event.get_number|slice:'1:-2'|cut:'/' }}"
|
||||||
data-search="{{ event.get_number }} ({{ event.get_sport_display }})">
|
data-search="{{ event.get_number }} ({{ event.get_sport_display }})">
|
||||||
<a href="{% url 'dav_events:event_detail' event.pk %}">{{ event.get_number }}</a><br />
|
<a href="{% url 'dav_events:detail' event.pk %}">{{ event.get_number }}</a><br />
|
||||||
<small>({{ event.get_sport_display }})</small>
|
<small>({{ event.get_sport_display }})</small>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="{% url 'dav_events:event_detail' event.pk %}">{{ event.title }}</a>
|
<a href="{% url 'dav_events:detail' event.pk %}">{{ event.title }}</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ event.get_trainer_full_name }}
|
{{ event.get_trainer_full_name }}
|
||||||
|
|||||||
@@ -6,17 +6,17 @@
|
|||||||
<div class="action-tabs">
|
<div class="action-tabs">
|
||||||
<div class="pull-right">
|
<div class="pull-right">
|
||||||
<a class="btn btn-primary"
|
<a class="btn btn-primary"
|
||||||
href="{% url 'dav_events:event_create' %}">
|
href="{% url 'dav_events:create' %}">
|
||||||
{% bootstrap_icon 'plus' %}
|
{% bootstrap_icon 'plus' %}
|
||||||
{% trans 'Neue Veranstaltung anlegen' %}
|
{% trans 'Neue Veranstaltung anlegen' %}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<ul class="nav nav-tabs" role="tablist">
|
<ul class="nav nav-tabs" role="tablist">
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'dav_events:event_list' %}">{% trans 'Veranstaltungsliste' %}</a>
|
<a href="{% url 'dav_events:list' %}">{% trans 'Veranstaltungsliste' %}</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="active">
|
<li class="active">
|
||||||
<a href="{% url 'dav_events:event_list_export' %}">{% trans 'Veranstaltungsliste herunterladen' %}</a>
|
<a href="{% url 'dav_events:list_export' %}">{% trans 'Veranstaltungsliste herunterladen' %}</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
{% bootstrap_icon 'download-alt' %} 
|
{% bootstrap_icon 'download-alt' %} 
|
||||||
{% trans 'Herunterladen' %}
|
{% trans 'Herunterladen' %}
|
||||||
</button>
|
</button>
|
||||||
<a class="btn btn-danger" href="{% url 'dav_events:event_list' %}">
|
<a class="btn btn-danger" href="{% url 'dav_events:list' %}">
|
||||||
{% bootstrap_icon 'remove' %} 
|
{% bootstrap_icon 'remove' %} 
|
||||||
{% trans 'Abbrechen' %}
|
{% trans 'Abbrechen' %}
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -8,13 +8,13 @@
|
|||||||
<div class="action-tabs">
|
<div class="action-tabs">
|
||||||
<ul class="nav nav-tabs" role="tablist">
|
<ul class="nav nav-tabs" role="tablist">
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'dav_events:event_list' %}">{% trans 'Veranstaltungsliste' %}</a>
|
<a href="{% url 'dav_events:list' %}">{% trans 'Veranstaltungsliste' %}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'dav_events:event_detail' event.pk %}">{% trans 'Details' %}</a>
|
<a href="{% url 'dav_events:detail' event.pk %}">{% trans 'Details' %}</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="active">
|
<li class="active">
|
||||||
<a href="{% url 'dav_events:event_update' event.pk %}">{% trans 'Ändern' %}</a>
|
<a href="{% url 'dav_events:update' event.pk %}">{% trans 'Ändern' %}</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
{% bootstrap_icon 'hdd' %} 
|
{% bootstrap_icon 'hdd' %} 
|
||||||
{% trans 'Speichern' %}
|
{% trans 'Speichern' %}
|
||||||
</button>
|
</button>
|
||||||
<a class="btn btn-danger" href="{% url 'dav_events:event_detail' event.pk %}">
|
<a class="btn btn-danger" href="{% url 'dav_events:detail' event.pk %}">
|
||||||
{% bootstrap_icon 'remove' %} 
|
{% bootstrap_icon 'remove' %} 
|
||||||
{% trans 'Abbrechen' %}
|
{% trans 'Abbrechen' %}
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
Du wirst dann per E-Mail auf dem laufenden gehalten.
|
Du wirst dann per E-Mail auf dem laufenden gehalten.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<a class="btn btn-primary" href="{% url 'dav_events:event_create' %}">Los geht's!</a>
|
<a class="btn btn-primary" href="{% url 'dav_events:create' %}">Los geht's!</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="well">
|
<div class="well">
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
Tourenreferenten und Redakteure können hier Veranstaltungen freigeben und Programmlisten herunterladen.
|
Tourenreferenten und Redakteure können hier Veranstaltungen freigeben und Programmlisten herunterladen.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<a class="btn btn-primary" href="{% url 'dav_events:event_list' %}">Weiter</a>
|
<a class="btn btn-primary" href="{% url 'dav_events:list' %}">Weiter</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{% endblock page-container-fluid %}
|
{% endblock page-container-fluid %}
|
||||||
+8
-12
@@ -3,18 +3,14 @@ from django.conf.urls import url
|
|||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^$', views.base.HomeView.as_view(), name='home'),
|
url(r'^home$', views.base.HomeView.as_view(), name='root'),
|
||||||
url(r'^user/login$', views.auth.LoginView.as_view(), name='login'),
|
url(r'^$', views.events.EventListView.as_view(), name='list'),
|
||||||
url(r'^user/logout$', views.auth.LogoutView.as_view(), name='logout'),
|
url(r'^export$', views.events.EventListExportView.as_view(), name='list_export'),
|
||||||
url(r'^user/password$', views.auth.SetPasswordView.as_view(), name='set_password'),
|
url(r'^create$', views.events.EventCreateView.as_view(), name='create'),
|
||||||
url(r'^user/password/reset$', views.auth.ResetPasswordView.as_view(), name='reset_password'),
|
url(r'^(?P<pk>\d+)/confirm/(?P<status>[a-z0-9][a-z0-9]*)',
|
||||||
url(r'^events$', views.events.EventListView.as_view(), name='event_list'),
|
views.events.EventConfirmStatusView.as_view(), name='confirmstatus'),
|
||||||
url(r'^events/export$', views.events.EventListExportView.as_view(), name='event_list_export'),
|
url(r'^(?P<pk>\d+)/edit', views.events.EventUpdateView.as_view(), name='update'),
|
||||||
url(r'^events/create$', views.events.EventCreateView.as_view(), name='event_create'),
|
url(r'^(?P<pk>\d+)/', views.events.EventDetailView.as_view(), name='detail'),
|
||||||
url(r'^events/(?P<pk>\d+)/confirm/(?P<status>[a-z0-9][a-z0-9]*)',
|
|
||||||
views.events.EventConfirmStatusView.as_view(), name='event_confirmstatus'),
|
|
||||||
url(r'^events/(?P<pk>\d+)/edit', views.events.EventUpdateView.as_view(), name='event_update'),
|
|
||||||
url(r'^events/(?P<pk>\d+)/', views.events.EventDetailView.as_view(), name='event_detail'),
|
|
||||||
url(r'^action/(?P<pk>[a-fA-F0-9]{8}-([a-fA-F0-9]{4}-){3}[a-fA-F0-9]{12})/',
|
url(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'),
|
||||||
]
|
]
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
from . import base
|
from . import base
|
||||||
from . import auth
|
|
||||||
from . import events
|
from . import events
|
||||||
from . import actions
|
from . import actions
|
||||||
@@ -20,7 +20,6 @@ from .. import models
|
|||||||
from ..utils import has_role
|
from ..utils import has_role
|
||||||
from ..workflow import workflow
|
from ..workflow import workflow
|
||||||
|
|
||||||
app_config = apps.get_containing_app_config(__package__)
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@@ -259,7 +258,7 @@ class EventCreateView(EventPermissionMixin, generic.FormView):
|
|||||||
form_class = forms.events.EventCreateForm
|
form_class = forms.events.EventCreateForm
|
||||||
template_dir = os.path.join('dav_events', 'event_create')
|
template_dir = os.path.join('dav_events', 'event_create')
|
||||||
default_template_name = 'default.html'
|
default_template_name = 'default.html'
|
||||||
abort_url = reverse_lazy('dav_events:home')
|
abort_url = reverse_lazy('dav_events:root')
|
||||||
|
|
||||||
def get_template_names(self):
|
def get_template_names(self):
|
||||||
form = self.get_form()
|
form = self.get_form()
|
||||||
@@ -317,7 +316,7 @@ class EventCreateView(EventPermissionMixin, generic.FormView):
|
|||||||
owner = event.owner
|
owner = event.owner
|
||||||
self.clean_session_data()
|
self.clean_session_data()
|
||||||
if self.request.user.is_authenticated:
|
if self.request.user.is_authenticated:
|
||||||
next_url = reverse('dav_events:event_list')
|
next_url = reverse('dav_events:list')
|
||||||
if self.request.user != event.owner:
|
if self.request.user != event.owner:
|
||||||
messages.warning(self.request,
|
messages.warning(self.request,
|
||||||
u'%s %s' % (
|
u'%s %s' % (
|
||||||
@@ -325,10 +324,10 @@ class EventCreateView(EventPermissionMixin, generic.FormView):
|
|||||||
_(u'Warum machst du sowas?')
|
_(u'Warum machst du sowas?')
|
||||||
))
|
))
|
||||||
elif owner.has_usable_password():
|
elif owner.has_usable_password():
|
||||||
next_url = reverse('dav_events:event_list')
|
next_url = reverse('dav_events:list')
|
||||||
else:
|
else:
|
||||||
login(self.request, owner)
|
login(self.request, owner)
|
||||||
next_url = reverse('dav_events:set_password')
|
next_url = reverse('dav_auth:set_password')
|
||||||
messages.success(self.request,
|
messages.success(self.request,
|
||||||
_(u'Neuen Benutzer angemeldet: %(username)s') % {'username': owner.username})
|
_(u'Neuen Benutzer angemeldet: %(username)s') % {'username': owner.username})
|
||||||
messages.warning(self.request, _(u'Bitte neues Passwort setzen!'))
|
messages.warning(self.request, _(u'Bitte neues Passwort setzen!'))
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ from django.apps import apps
|
|||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from . import emails
|
from . import emails
|
||||||
|
from .utils import get_users_by_role
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -143,7 +144,6 @@ class BasicWorkflow(object):
|
|||||||
recipients = [event.owner]
|
recipients = [event.owner]
|
||||||
if event.is_flagged('submitted'):
|
if event.is_flagged('submitted'):
|
||||||
# If the event is already submitted, add managers to the recipients.
|
# If the event is already submitted, add managers to the recipients.
|
||||||
from .utils import get_users_by_role
|
|
||||||
recipients += get_users_by_role('manage_all')
|
recipients += get_users_by_role('manage_all')
|
||||||
recipients += get_users_by_role('manage_{}'.format(event.sport.lower()))
|
recipients += get_users_by_role('manage_{}'.format(event.sport.lower()))
|
||||||
if event.is_flagged('accepted'):
|
if event.is_flagged('accepted'):
|
||||||
@@ -174,7 +174,6 @@ class BasicWorkflow(object):
|
|||||||
# Inform managers that they have to accept the event.
|
# Inform managers that they have to accept the event.
|
||||||
# Also create OneClickActions for all of them and add the link to the mail,
|
# Also create OneClickActions for all of them and add the link to the mail,
|
||||||
# so they can accept the event with a click into the mail.
|
# so they can accept the event with a click into the mail.
|
||||||
from .utils import get_users_by_role
|
|
||||||
recipients = get_users_by_role('manage_all')
|
recipients = get_users_by_role('manage_all')
|
||||||
recipients += get_users_by_role('manage_{}'.format(event.sport.lower()))
|
recipients += get_users_by_role('manage_{}'.format(event.sport.lower()))
|
||||||
OneClickAction = app_config.get_model('OneClickAction')
|
OneClickAction = app_config.get_model('OneClickAction')
|
||||||
@@ -195,7 +194,6 @@ class BasicWorkflow(object):
|
|||||||
# Inform publishers that they have to publish the event.
|
# Inform publishers that they have to publish the event.
|
||||||
# Also create OneClickActions for all of them and add the link to the mail,
|
# Also create OneClickActions for all of them and add the link to the mail,
|
||||||
# so they can confirm the publication with a click into the mail.
|
# so they can confirm the publication with a click into the mail.
|
||||||
from .utils import get_users_by_role
|
|
||||||
recipients = get_users_by_role('publish_incremental')
|
recipients = get_users_by_role('publish_incremental')
|
||||||
OneClickAction = app_config.get_model('OneClickAction')
|
OneClickAction = app_config.get_model('OneClickAction')
|
||||||
for recipient in recipients:
|
for recipient in recipients:
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ if sys.version_info.major != 2:
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='django-dav-events',
|
name='django-dav-events',
|
||||||
version='0.2',
|
version='1.0',
|
||||||
description='A django based web application project to submit DAV Events.',
|
description='A django based web application project to submit DAV Events.',
|
||||||
url='https://www.heinzelwelt.de',
|
url='https://www.heinzelwelt.de',
|
||||||
maintainer='Jens Kleineheismann',
|
maintainer='Jens Kleineheismann',
|
||||||
@@ -57,7 +57,7 @@ setup(
|
|||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
entry_points={
|
entry_points={
|
||||||
'console_scripts': [
|
'console_scripts': [
|
||||||
'django-dav-events-admin = dav_events.console_scripts.admin:main',
|
'django-dav-admin = dav_base.console_scripts.admin:main',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
install_requires=[
|
install_requires=[
|
||||||
|
|||||||
Reference in new issue
Block a user