Seperated some config settings from code.

This commit is contained in:
2018-01-26 14:28:09 +01:00
parent c250854cbe
commit 5cf05666ab
9 changed files with 231 additions and 137 deletions

View File

@@ -1,6 +1,5 @@
- beim Erstellen einer neuen Veranstaltung wird nach event.trainer_email = user.username gesucht, evtl. wäre - beim Erstellen einer neuen Veranstaltung wird nach event.trainer_email = user.username gesucht, evtl. wäre
event.trainer_email = user.email besser? event.trainer_email = user.email besser?
- echte config nicht im repository verwalten.
- Anzeige Bahnfahrt - Anzeige Bahnfahrt
- ApproachForm aufteilen - ApproachForm aufteilen
- Anmeldungstext - Anmeldungstext
@@ -11,7 +10,7 @@
- Save as Draft - Save as Draft
- Copy Event - Copy Event
- Tourenreferent managed Gruppen der Subreferenten - Tourenreferent managed Gruppen der Subreferenten
- Initialtexte und Placeholder von forms in config - Initialtexte und Placeholder von forms in config/app_config
- Passwort vergessen Funktion - Passwort vergessen Funktion
- Besserer Zurück-Button in Formulare - Besserer Zurück-Button in Formulare

View File

@@ -1,6 +1,25 @@
from django.apps import AppConfig as _AppConfig from django.core.exceptions import ImproperlyConfigured
from .config import AppConfig as _AppConfig, DefaultSetting
DEFAULT_SETTINGS = (
DefaultSetting('enable_email_notifications', False),
DefaultSetting('email_sender', None),
DefaultSetting('email_base_url', None),
DefaultSetting('manage_all_group', None),
DefaultSetting('manage_w_group', None),
DefaultSetting('manage_s_group', None),
DefaultSetting('manage_m_group', None),
DefaultSetting('manage_k_group', None),
DefaultSetting('manage_b_group', None),
DefaultSetting('publisher_group', None),
DefaultSetting('incremental_publisher_group', None),
DefaultSetting('development_init_forms', False),
DefaultSetting('fee_matrix', ImproperlyConfigured),
)
class AppConfig(_AppConfig): class AppConfig(_AppConfig):
name = 'dav_events' name = 'dav_events'
verbose_name = u'DAV Veranstaltungen' verbose_name = u'DAV Veranstaltungen'
default_settings = DEFAULT_SETTINGS

View File

@@ -1,31 +1,14 @@
# -*- coding: utf-8 -*- import importlib
from django.utils.translation import ugettext_lazy as _ import re
from django.apps import AppConfig as _AppConfig
from django.core.exceptions import ImproperlyConfigured
# E-Mails # Form and Model Field Config
ENABLE_EMAIL_NOTIFICATIONS = True
EMAIL_SENDER = 'Jens Kleineheismann <kleineheismann@kit.edu>'
EMAIL_BASE_URL = 'http://localhost:8000'
# Auth Config
MANAGE_ALL_GROUP = 'Tourenreferenten'
MANAGE_W_GROUP = 'Wanderreferenten'
MANAGE_S_GROUP = 'Skireferenten'
MANAGE_M_GROUP = 'MTBReferenten'
MANAGE_K_GROUP = 'Kletterreferenten'
MANAGE_B_GROUP = 'Bergsteigerreferenten'
PUBLISHER_GROUP = 'Redaktion'
INCREMENTAL_PUBLISHER_GROUP = 'OnlineRedaktion'
# Form Config
COMMON_CHAR_FIELD_LENGTH = 250 COMMON_CHAR_FIELD_LENGTH = 250
NUMBER_MAX_LENGTH = 12 NUMBER_MAX_LENGTH = 12
TITLE_MAX_LENGTH = COMMON_CHAR_FIELD_LENGTH TITLE_MAX_LENGTH = COMMON_CHAR_FIELD_LENGTH
TRAINER_NAME_MAX_LENGTH = COMMON_CHAR_FIELD_LENGTH TRAINER_NAME_MAX_LENGTH = COMMON_CHAR_FIELD_LENGTH
PHONE_NUMBER_MAX_LENGTH = COMMON_CHAR_FIELD_LENGTH PHONE_NUMBER_MAX_LENGTH = COMMON_CHAR_FIELD_LENGTH
LOCATION_MAX_LENGTH = COMMON_CHAR_FIELD_LENGTH LOCATION_MAX_LENGTH = COMMON_CHAR_FIELD_LENGTH
TRANSPORT_OTHER_MAX_LENGTH = COMMON_CHAR_FIELD_LENGTH TRANSPORT_OTHER_MAX_LENGTH = COMMON_CHAR_FIELD_LENGTH
MEETING_POINT_OTHER_MAX_LENGTH = COMMON_CHAR_FIELD_LENGTH MEETING_POINT_OTHER_MAX_LENGTH = COMMON_CHAR_FIELD_LENGTH
@@ -34,89 +17,66 @@ ACCOMMODATION_OTHER_MAX_LENGTH = COMMON_CHAR_FIELD_LENGTH
MEALS_OTHER_MAX_LENGTH = COMMON_CHAR_FIELD_LENGTH MEALS_OTHER_MAX_LENGTH = COMMON_CHAR_FIELD_LENGTH
ADDITIONAL_COSTS_MAX_LENGTH = COMMON_CHAR_FIELD_LENGTH ADDITIONAL_COSTS_MAX_LENGTH = COMMON_CHAR_FIELD_LENGTH
FEE_MATRIX = {
'0': {'description': _(u'Keiner / direkte Abrechnung (Tageswanderung)'), class DefaultSetting(object):
'trainer_fee': 0, def __init__(self, name, value, key_name=None, validator=None):
'pre_meeting_fee': 0, self.name = name
'trainer_day_fee': 0, self.value = value
'participant_fee': 0, if key_name is None:
'participant_day_fee': 0, self.key_name = self.name.upper()
}, else:
'A': {'description': _(u'A (Mehrtageswanderung Mittelgebirge'), self.key_name = key_name
'trainer_fee': 40, self.validator = validator
'trainer_day_fee': 50,
'participant_fee': 10, def validate(self, value):
'participant_day_fee': 10, if hasattr(self, 'validator') and self.validator is not None:
'pre_meeting_fee': 0, if callable(self.validator):
}, if not self.validator(value):
'B': {'description': _(u'B (Alpine Mehrtageswanderung)'), raise ImproperlyConfigured("Validator callback {clb} returned False".format(clb=self.validator))
'trainer_fee': 50, else:
'trainer_day_fee': 75, if not re.search(self.validator, value):
'participant_fee': 10, raise ImproperlyConfigured("Does not match /{re}/".format(re=self.validator))
'participant_day_fee': 20,
'pre_meeting_fee': 0,
}, class AppSettings(object):
'C': {'description': _(u'C (Tour/Kurs ohne Übernachtung)'), def __init__(self, app_name, defaults):
'trainer_fee': 30, settings_name = 'main.settings-' + app_name
'trainer_day_fee': 60,
'participant_fee': 10, try:
'participant_day_fee': 30, settings_module = importlib.import_module(settings_name)
'pre_meeting_fee': 0, except ImportError:
}, settings_module = None
'D': {'description': _(u'D (Tour/Kurs Mittelgebirge)'),
'trainer_fee': 50, for default in defaults:
'trainer_day_fee': 75, if hasattr(settings_module, default.key_name):
'participant_fee': 20, value = getattr(settings_module, default.key_name)
'participant_day_fee': 25, try:
'pre_meeting_fee': 0, default.validate(value)
}, except ImproperlyConfigured as e:
'E': {'description': _(u'E (Alpine Klettertour DE/AU)'), msg = 'Invalid value of {key} in {module}: {cause}'.format(key=default.key_name,
'trainer_fee': 80, module=settings_name,
'trainer_day_fee': 75, cause=e.message)
'participant_fee': 40, raise ImproperlyConfigured(msg)
'participant_day_fee': 40, setattr(self, default.name, value)
'pre_meeting_fee': 0, elif isinstance(default.value, ImproperlyConfigured):
}, raise default.value
'F': {'description': _(u'F (Alpine Klettertour CH/FR/IT)'), else:
'trainer_fee': 80, try:
'trainer_day_fee': 85, is_impconf = issubclass(default.value, ImproperlyConfigured)
'participant_fee': 40, except TypeError:
'participant_day_fee': 45, is_impconf = False
'pre_meeting_fee': 0,
}, if is_impconf:
'G': {'description': _(u'G (Alpiner Kurs DE/AU)'), msg = '{key} must be defined in {module}'.format(key=default.key_name,
'trainer_fee': 100, module=settings_name)
'trainer_day_fee': 75, raise default.value(msg)
'participant_fee': 35, else:
'participant_day_fee': 30, setattr(self, default.name, default.value)
'pre_meeting_fee': 0,
},
'H': {'description': _(u'H (Alpiner Kurs CH/FR/IT/..)'), class AppConfig(_AppConfig):
'trainer_fee': 100, default_settings = ()
'trainer_day_fee': 85,
'participant_fee': 35, def __init__(self, app_name, app_module):
'participant_day_fee': 30, super(AppConfig, self).__init__(app_name, app_module)
'pre_meeting_fee': 0, self.settings = AppSettings(app_name, self.default_settings)
},
'I': {'description': _(u'I (Alpine MTB/Ski-Tour DE/AU)'),
'trainer_fee': 80,
'trainer_day_fee': 75,
'participant_fee': 25,
'participant_day_fee': 25,
'pre_meeting_fee': 0,
},
'J': {'description': _(u'J (Alpine MTB/Ski-Tour CH/FR/IT/..)'),
'trainer_fee': 80,
'trainer_day_fee': 85,
'participant_fee': 25,
'participant_day_fee': 25,
'pre_meeting_fee': 0,
},
'K': {'description': _(u'K (Ski-Tour/-Kurs mit Liftbenutzung)'),
'trainer_fee': 80,
'trainer_day_fee': 130,
'participant_fee': 40,
'participant_day_fee': 40,
'pre_meeting_fee': 0,
},
}

View File

@@ -38,7 +38,9 @@ LOGGING = {
'format': '%(asctime)s - %(name)s - %(levelname)s: %(message)s' 'format': '%(asctime)s - %(name)s - %(levelname)s: %(message)s'
}, },
'verbose': { 'verbose': {
'format': '%(asctime)s -- %(processName)s[%(process)d]:%(threadName)s[%(thread)d] -- %(name)s -- %(module)s...%(funcName)s() -- %(pathname)s:%(lineno)d -- %(levelname)s: %(message)s' 'format': ('%(asctime)s -- %(processName)s[%(process)d]:%(threadName)s[%(thread)d] -- '
'%(name)s -- %(module)s...%(funcName)s() -- %(pathname)s:%(lineno)d -- '
'%(levelname)s: %(message)s')
}, },
}, },
'filters': { 'filters': {

View File

@@ -0,0 +1,106 @@
# -*- coding: utf-8 -*-
from django.utils.translation import ugettext_lazy as _
# E-Mails
ENABLE_EMAIL_NOTIFICATIONS = False
EMAIL_SENDER = 'Jens Kleineheismann <kleineheismann@kit.edu>'
EMAIL_BASE_URL = 'http://localhost:8000'
# Auth Config
MANAGE_ALL_GROUP = 'Tourenreferenten'
MANAGE_W_GROUP = 'Wanderreferenten'
MANAGE_S_GROUP = 'Skireferenten'
MANAGE_M_GROUP = 'MTBReferenten'
MANAGE_K_GROUP = 'Kletterreferenten'
MANAGE_B_GROUP = 'Bergsteigerreferenten'
PUBLISHER_GROUP = 'Redaktion'
INCREMENTAL_PUBLISHER_GROUP = 'OnlineRedaktion'
# EventCreateForm
# DEVELOPMENT_INIT_FORMS = False
FEE_MATRIX = {
'0': {'description': _(u'Keiner / direkte Abrechnung (Tageswanderung)'),
'trainer_fee': 0,
'pre_meeting_fee': 0,
'trainer_day_fee': 0,
'participant_fee': 0,
'participant_day_fee': 0,
},
'A': {'description': _(u'A (Mehrtageswanderung Mittelgebirge'),
'trainer_fee': 40,
'trainer_day_fee': 50,
'participant_fee': 10,
'participant_day_fee': 10,
'pre_meeting_fee': 0,
},
'B': {'description': _(u'B (Alpine Mehrtageswanderung)'),
'trainer_fee': 50,
'trainer_day_fee': 75,
'participant_fee': 10,
'participant_day_fee': 20,
'pre_meeting_fee': 0,
},
'C': {'description': _(u'C (Tour/Kurs ohne Übernachtung)'),
'trainer_fee': 30,
'trainer_day_fee': 60,
'participant_fee': 10,
'participant_day_fee': 30,
'pre_meeting_fee': 0,
},
'D': {'description': _(u'D (Tour/Kurs Mittelgebirge)'),
'trainer_fee': 50,
'trainer_day_fee': 75,
'participant_fee': 20,
'participant_day_fee': 25,
'pre_meeting_fee': 0,
},
'E': {'description': _(u'E (Alpine Klettertour DE/AU)'),
'trainer_fee': 80,
'trainer_day_fee': 75,
'participant_fee': 40,
'participant_day_fee': 40,
'pre_meeting_fee': 0,
},
'F': {'description': _(u'F (Alpine Klettertour CH/FR/IT)'),
'trainer_fee': 80,
'trainer_day_fee': 85,
'participant_fee': 40,
'participant_day_fee': 45,
'pre_meeting_fee': 0,
},
'G': {'description': _(u'G (Alpiner Kurs DE/AU)'),
'trainer_fee': 100,
'trainer_day_fee': 75,
'participant_fee': 35,
'participant_day_fee': 30,
'pre_meeting_fee': 0,
},
'H': {'description': _(u'H (Alpiner Kurs CH/FR/IT/..)'),
'trainer_fee': 100,
'trainer_day_fee': 85,
'participant_fee': 35,
'participant_day_fee': 30,
'pre_meeting_fee': 0,
},
'I': {'description': _(u'I (Alpine MTB/Ski-Tour DE/AU)'),
'trainer_fee': 80,
'trainer_day_fee': 75,
'participant_fee': 25,
'participant_day_fee': 25,
'pre_meeting_fee': 0,
},
'J': {'description': _(u'J (Alpine MTB/Ski-Tour CH/FR/IT/..)'),
'trainer_fee': 80,
'trainer_day_fee': 85,
'participant_fee': 25,
'participant_day_fee': 25,
'pre_meeting_fee': 0,
},
'K': {'description': _(u'K (Ski-Tour/-Kurs mit Liftbenutzung)'),
'trainer_fee': 80,
'trainer_day_fee': 130,
'participant_fee': 40,
'participant_day_fee': 40,
'pre_meeting_fee': 0,
},
}

View File

@@ -78,6 +78,11 @@ class AdminCommand(object):
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')
output_file = os.path.join(django_project_path, django_project_name, 'settings-dav_events.py')
with open(output_file, 'w') as f:
f.write(pkg_resources.resource_string(__package__, input_file))
return posix.EX_OK return posix.EX_OK
def __init__(self): def __init__(self):

View File

@@ -1,32 +1,33 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import logging import logging
from django.apps import apps
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.core.mail import EmailMessage from django.core.mail import EmailMessage
from django.template.loader import get_template from django.template.loader import get_template
from . import config
from .utils import get_group_members from .utils import get_group_members
app_config = apps.get_containing_app_config(__package__)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def get_recipients(task, sport=None): def get_recipients(task, sport=None):
users = [] users = []
if task == 'accept': if task == 'accept':
group_var_name = 'MANAGE_ALL_GROUP' group_var_name = 'manage_all_group'
group_name = getattr(config, group_var_name, None) group_name = getattr(app_config.settings, group_var_name, None)
if group_name: if group_name:
users.extend(get_group_members(group_name, ignore_missing=True)) users.extend(get_group_members(group_name, ignore_missing=True))
if sport: if sport:
group_var_name = 'MANAGE_{}_GROUP'.format(sport) group_var_name = 'manage_{}_group'.format(sport.lower())
group_name = getattr(config, group_var_name, None) group_name = getattr(app_config.settings, group_var_name, None)
if group_name: if group_name:
users.extend(get_group_members(group_name, ignore_missing=True)) users.extend(get_group_members(group_name, ignore_missing=True))
elif task == 'publish': elif task == 'publish':
group_var_name = 'INCREMENTAL_PUBLISHER_GROUP' group_var_name = 'incremental_publisher_group'
group_name = getattr(config, group_var_name, None) group_name = getattr(app_config.settings, group_var_name, None)
if group_name: if group_name:
users.extend(get_group_members(group_name, ignore_missing=True)) users.extend(get_group_members(group_name, ignore_missing=True))
else: else:
@@ -36,7 +37,7 @@ def get_recipients(task, sport=None):
class AbstractMail(object): class AbstractMail(object):
_sender = config.EMAIL_SENDER _sender = app_config.settings.email_sender
_subject = 'Generic Mail' _subject = 'Generic Mail'
_template_name = None _template_name = None
@@ -50,7 +51,7 @@ class AbstractMail(object):
def _get_context_data(self, extra_context=None): def _get_context_data(self, extra_context=None):
context = { context = {
'base_url': config.EMAIL_BASE_URL, 'base_url': app_config.settings.email_base_url,
} }
if extra_context: if extra_context:
context.update(extra_context) context.update(extra_context)
@@ -65,7 +66,7 @@ class AbstractMail(object):
raise NotImplementedError() raise NotImplementedError()
def send(self): def send(self):
if not config.ENABLE_EMAIL_NOTIFICATIONS: if not app_config.settings.enable_email_notifications:
return None return None
subject = self._get_subject() subject = self._get_subject()
body = self._get_body() body = self._get_body()

View File

@@ -4,6 +4,7 @@ import datetime
import logging import logging
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.utils.translation import get_language, ugettext, ugettext_lazy as _ from django.utils.translation import get_language, ugettext, ugettext_lazy as _
from django_countries.fields import LazyTypedChoiceField from django_countries.fields import LazyTypedChoiceField
from datetimewidget.widgets import DateWidget, TimeWidget, DateTimeWidget from datetimewidget.widgets import DateWidget, TimeWidget, DateTimeWidget
@@ -13,8 +14,8 @@ from .. import config
from .. import models from .. import models
from .generic import ChainedForm from .generic import ChainedForm
app_config = apps.get_containing_app_config(__package__)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
DEVELOPMENT_INIT_FORMS = False
class EventUpdateForm(forms.ModelForm): class EventUpdateForm(forms.ModelForm):
@@ -207,7 +208,7 @@ class LocationForm(EventCreateForm):
elif sport == 'W': elif sport == 'W':
self.fields['location'].widget.attrs['placeholder'] = u'Maikammer, Pfalz' self.fields['location'].widget.attrs['placeholder'] = u'Maikammer, Pfalz'
if DEVELOPMENT_INIT_FORMS: if app_config.settings.development_init_forms:
self.fields['location'].initial = self.fields['location'].widget.attrs['placeholder'] self.fields['location'].initial = self.fields['location'].widget.attrs['placeholder']
@@ -478,7 +479,7 @@ class DescriptionForm(EventCreateForm):
elif sport == 'W' and not last_day: elif sport == 'W' and not last_day:
title_prefix += u'%s ' % ugettext(u'Tageswanderung') title_prefix += u'%s ' % ugettext(u'Tageswanderung')
if DEVELOPMENT_INIT_FORMS: if app_config.settings.development_init_forms:
if not title_prefix: if not title_prefix:
title_prefix = u'%s' % choices.SPORT_CHOICES.get_label(sport) title_prefix = u'%s' % choices.SPORT_CHOICES.get_label(sport)
@@ -609,7 +610,7 @@ class TrainerForm(EventCreateForm):
self.fields['trainer_firstname'].initial = self._request.user.first_name self.fields['trainer_firstname'].initial = self._request.user.first_name
self.fields['trainer_familyname'].initial = self._request.user.last_name self.fields['trainer_familyname'].initial = self._request.user.last_name
self.fields['trainer_email'].initial = self._request.user.email self.fields['trainer_email'].initial = self._request.user.email
elif DEVELOPMENT_INIT_FORMS: elif app_config.settings.development_init_forms:
self.fields['trainer_firstname'].initial = self.fields['trainer_firstname'].widget.attrs['placeholder'] self.fields['trainer_firstname'].initial = self.fields['trainer_firstname'].widget.attrs['placeholder']
self.fields['trainer_familyname'].initial = self.fields['trainer_familyname'].widget.attrs['placeholder'] self.fields['trainer_familyname'].initial = self.fields['trainer_familyname'].widget.attrs['placeholder']
self.fields['trainer_email'].initial = self.fields['trainer_email'].widget.attrs['placeholder'] self.fields['trainer_email'].initial = self.fields['trainer_email'].widget.attrs['placeholder']
@@ -712,7 +713,7 @@ class ChargesForm(EventCreateForm):
else: else:
n_pre_meetings = 0 n_pre_meetings = 0
fees = config.FEE_MATRIX[charge_key] fees = app_config.settings.fee_matrix[charge_key]
trainer_reward = ( trainer_reward = (
fees['trainer_fee'] fees['trainer_fee']

View File

@@ -1,5 +1,6 @@
import logging import logging
import os import os
from django.apps import apps
from django.contrib import messages from django.contrib import messages
from django.contrib.auth import login from django.contrib.auth import login
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
@@ -11,10 +12,10 @@ from django.utils.decorators import method_decorator
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 config
from .. import forms from .. import forms
from .. import models from .. import models
app_config = apps.get_containing_app_config(__package__)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -25,13 +26,13 @@ class EventListView(generic.ListView):
user = self.request.user user = self.request.user
if user.is_superuser: if user.is_superuser:
qs = self.model.objects.all() qs = self.model.objects.all()
elif user.groups.filter(name=config.MANAGE_ALL_GROUP).count(): elif user.groups.filter(name=app_config.settings.manage_all_group).count():
qs = self.model.objects.all() qs = self.model.objects.all()
else: else:
user_sports_list = list() user_sports_list = list()
for k in ('W', 'S', 'M', 'K', 'B'): for k in ('W', 'S', 'M', 'K', 'B'):
group_name_var = 'MANAGE_{}_GROUP'.format(k) group_name_var = 'manage_{}_group'.format(k.lower())
group_name = getattr(config, group_name_var, None) group_name = getattr(app_config.settings, group_name_var, None)
if group_name and user.groups.filter(name=group_name).count(): if group_name and user.groups.filter(name=group_name).count():
user_sports_list.append(k) user_sports_list.append(k)
qs = self.model.objects.filter(Q(owner=user) | Q(sport__in=user_sports_list)) qs = self.model.objects.filter(Q(owner=user) | Q(sport__in=user_sports_list))
@@ -55,17 +56,17 @@ class EventPermissionMixin(object):
if permission == 'view': if permission == 'view':
if obj.owner == user: if obj.owner == user:
return True return True
if user.groups.filter(name=config.MANAGE_ALL_GROUP).count(): if user.groups.filter(name=app_config.settings.manage_all_group).count():
return True return True
group_name_var = 'MANAGE_{}_GROUP'.format(obj.sport) group_name_var = 'manage_{}_group'.format(obj.sport.lower())
group_name = getattr(config, group_name_var, None) group_name = getattr(app_config.settings, group_name_var, None)
if group_name and user.groups.filter(name=group_name).count(): if group_name and user.groups.filter(name=group_name).count():
return True return True
elif permission in ('update', 'accept'): elif permission in ('update', 'accept'):
if user.groups.filter(name=config.MANAGE_ALL_GROUP).count(): if user.groups.filter(name=app_config.settings.manage_all_group).count():
return True return True
group_name_var = 'MANAGE_{}_GROUP'.format(obj.sport) group_name_var = 'manage_{}_group'.format(obj.sport)
group_name = getattr(config, group_name_var, None) group_name = getattr(app_config.settings, group_name_var, None)
if group_name and user.groups.filter(name=group_name).count(): if group_name and user.groups.filter(name=group_name).count():
return True return True