Add system wide gym configuration options

At the moment this only allows the administrator to set a default
gym for the installation.
This commit is contained in:
Roland Geider
2014-08-11 20:24:34 +02:00
parent 24c67d0aa9
commit 17fca8e0a5
11 changed files with 295 additions and 6 deletions

View File

@@ -60,7 +60,12 @@ filter_dump(data, ('exercises.equipment', 'exercises.equipment',), 'equipment.js
filter_dump(data, ('core.gym',), 'gyms.json')
filter_dump(data, ('core.language',), 'languages.json')
filter_dump(data, ('core.license',), 'licenses.json')
#
# Configurations
#
filter_dump(data, ('config.languageconfig',), 'language_config.json')
filter_dump(data, ('config.gymconfig',), 'gym-config.json')
#
# Other

View File

@@ -0,0 +1,9 @@
[
{
"pk": 1,
"model": "config.gymconfig",
"fields": {
"default_gym": null
}
}
]

View File

@@ -0,0 +1,69 @@
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'GymConfig'
db.create_table(u'config_gymconfig', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('default_gym', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['core.Gym'], null=True, blank=True)),
))
db.send_create_signal(u'config', ['GymConfig'])
# Changing field 'LanguageConfig.language_target'
db.alter_column(u'config_languageconfig', 'language_target_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['core.Language']))
# Changing field 'LanguageConfig.language'
db.alter_column(u'config_languageconfig', 'language_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['core.Language']))
def backwards(self, orm):
# Deleting model 'GymConfig'
db.delete_table(u'config_gymconfig')
# Changing field 'LanguageConfig.language_target'
db.alter_column(u'config_languageconfig', 'language_target_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['exercises.Language']))
# Changing field 'LanguageConfig.language'
db.alter_column(u'config_languageconfig', 'language_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['exercises.Language']))
models = {
u'config.gymconfig': {
'Meta': {'object_name': 'GymConfig'},
'default_gym': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['core.Gym']", 'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
u'config.languageconfig': {
'Meta': {'ordering': "['item', 'language_target']", 'object_name': 'LanguageConfig'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'item': ('django.db.models.fields.CharField', [], {'max_length': '2'}),
'language': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'language_source'", 'to': u"orm['core.Language']"}),
'language_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'language_target'", 'to': u"orm['core.Language']"}),
'show': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
u'core.gym': {
'Meta': {'object_name': 'Gym'},
'city': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '60'}),
'owner': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'phone': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}),
'street': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}),
'zip_code': ('django.db.models.fields.IntegerField', [], {'max_length': '5', 'null': 'True', 'blank': 'True'})
},
u'core.language': {
'Meta': {'ordering': "['full_name']", 'object_name': 'Language'},
'full_name': ('django.db.models.fields.CharField', [], {'max_length': '30'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'short_name': ('django.db.models.fields.CharField', [], {'max_length': '2'})
}
}
complete_apps = ['config']

View File

@@ -22,6 +22,8 @@ from django.db.models.signals import post_save
from django.utils.translation import ugettext_lazy as _
from django.core.cache import cache
from wger.core.models import Language
from wger.core.models import Gym
from wger.core.models import UserProfile
from wger.utils.cache import delete_template_fragment_cache
from wger.utils.cache import cache_mapper
@@ -119,3 +121,38 @@ def init_language_config(sender, instance, created, **kwargs):
config.show = False
config.save()
post_save.connect(init_language_config, sender=Language)
class GymConfig(models.Model):
'''
System wide configuration for gyms
At the moment this only allows to set one gym as the default
'''
default_gym = models.ForeignKey(Gym,
verbose_name=_('Default gym'),
help_text=_('Select the default gym for this installation. '
'This will assign all new registered users to this '
'gym and update all existing users without a '
'gym.'),
null=True,
blank=True)
'''
Default gym for the wger installation
'''
def __unicode__(self):
'''
Return a more human-readable representation
'''
return u"Default gym {0}".format(self.gym)
def save(self, *args, **kwargs):
'''
All users that have no gym set in the profile are edited
'''
if self.default_gym:
UserProfile.objects.filter(gym=None).update(gym=self.default_gym)
return super(GymConfig, self).save(*args, **kwargs)

View File

@@ -0,0 +1,86 @@
# -*- coding: utf-8 -*-
# This file is part of wger Workout Manager.
#
# wger Workout Manager is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# wger Workout Manager is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with Workout Manager. If not, see <http://www.gnu.org/licenses/>.
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from wger.config.models import GymConfig
from wger.core.models import Gym, UserProfile
from wger.manager.tests.testcase import WorkoutManagerTestCase
class GymConfigTestCase(WorkoutManagerTestCase):
'''
Test the system wide gym configuration
'''
def test_default_gym(self):
'''
Test that newly registered users get a gym
'''
gym = Gym.objects.get(pk=2)
gym_config = GymConfig.objects.get(pk=1)
gym_config.default_gym = gym
gym_config.save()
# Register
registration_data = {'username': 'myusername',
'password1': 'secret',
'password2': 'secret',
'email': 'my.email@example.com',
'recaptcha_response_field': 'PASSED', }
self.client.post(reverse('core:registration'), registration_data)
new_user = User.objects.get(pk=4)
self.assertEqual(new_user.userprofile.gym, gym)
def test_no_default_gym(self):
'''
Test the user registration without a default gym
'''
gym = Gym.objects.get(pk=2)
gym_config = GymConfig.objects.get(pk=1)
gym_config.default_gym = None
gym_config.save()
# Register
registration_data = {'username': 'myusername',
'password1': 'secret',
'password2': 'secret',
'email': 'my.email@example.com',
'recaptcha_response_field': 'PASSED', }
self.client.post(reverse('core:registration'), registration_data)
new_user = User.objects.get(pk=4)
self.assertEqual(new_user.userprofile.gym_id, None)
def test_update_userprofile(self):
'''
Test setting the gym for users when setting a default gym
'''
UserProfile.objects.update(gym=None)
self.assertEqual(UserProfile.objects.exclude(gym=None).count(), 0)
gym = Gym.objects.get(pk=2)
gym_config = GymConfig.objects.get(pk=1)
gym_config.default_gym = gym
gym_config.save()
self.assertEqual(UserProfile.objects.filter(gym=gym).count(), 3)

View File

@@ -19,6 +19,7 @@ from django.conf.urls import patterns, url
from wger.config.views import languages
from wger.config.views import language_config
from wger.config.views import gym_config
urlpatterns = patterns('',
@@ -40,8 +41,13 @@ urlpatterns = patterns('',
languages.LanguageCreateView.as_view(),
name='language-add'),
# Language configs
url(r'^language/config/(?P<pk>\d+)/edit',
language_config.LanguageConfigUpdateView.as_view(),
name='languageconfig-edit'),
# Language configs
url(r'^language-config/(?P<pk>\d+)/edit',
language_config.LanguageConfigUpdateView.as_view(),
name='languageconfig-edit'),
# Gym config
url(r'^default-gym',
gym_config.GymConfigUpdateView.as_view(),
name='gymconfig-edit'),
)

View File

@@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
# This file is part of wger Workout Manager.
#
# wger Workout Manager is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# wger Workout Manager is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
import logging
from django.core.urlresolvers import reverse
from django.core.urlresolvers import reverse_lazy
from django.utils.translation import ugettext as _
from django.views.generic import UpdateView
from wger.config.models import GymConfig
from wger.utils.generic_views import WgerFormMixin
logger = logging.getLogger('wger.custom')
class GymConfigUpdateView(WgerFormMixin, UpdateView):
'''
Generic view to edit the gym config table
'''
model = GymConfig
permission_required = 'config.change_gymconfig'
success_url = reverse_lazy('config:gymconfig-edit')
def get_object(self):
'''
Return the only gym config object
'''
return GymConfig.objects.get(pk=1)
def get_context_data(self, **kwargs):
context = super(GymConfigUpdateView, self).get_context_data(**kwargs)
context['form_action'] = reverse('config:gymconfig-edit')
context['title'] = _('Edit')
return context

View File

@@ -36,7 +36,7 @@
{% block sidebar %}
{% if perms.core.add_gym %}
<h3>{% trans "Options" %}</h3>
<h4>{% trans "Options" %}</h4>
<p>
<a href="{% url 'core:gym-add' %}"
{% auto_link_css flavour "wger-modal-dialog" %}>
@@ -49,4 +49,19 @@
</a>
</p>
{% endif %}
{% if perms.core.change_gymconfig %}
<h4>{% trans "Default gym" %}</h4>
<p>
<a href="{% url 'config:gymconfig-edit' %}"
{% auto_link_css flavour %}>
<img src="{% static 'images/icons/list.svg' %}"
width="32"
height="32"
alt="{% trans 'Default gym configuration' %}"
title="{% trans 'Default gym configuration' %}">
{% trans "Default gym configuration" %}
</a>
</p>
{% endif %}
{% endblock %}

View File

@@ -42,6 +42,7 @@ from wger.core.forms import UserPreferencesForm, UserPersonalInformationForm
from wger.core.forms import PasswordConfirmationForm
from wger.core.forms import RegistrationForm
from wger.core.forms import RegistrationFormNoCaptcha
from wger.config.models import GymConfig
logger = logging.getLogger('wger.custom')
@@ -168,9 +169,14 @@ def registration(request):
password)
user.save()
# Save the notification language
# Pre-set some values of the user's profile
language = Language.objects.get(short_name=translation.get_language())
user.userprofile.notification_language = language
gym_config = GymConfig.objects.get(pk=1)
if gym_config:
user.userprofile.gym = gym_config.default_gym
user.userprofile.save()
user = authenticate(username=username, password=password)

View File

@@ -51,6 +51,7 @@ class BaseTestCase(object):
'''
fixtures = ('days_of_week',
'gym-config',
'test-languages',
'test-licenses',
'test-gyms',

View File

@@ -348,3 +348,9 @@ REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.DjangoFilterBackend',
'rest_framework.filters.OrderingFilter',)
}
# Configure south database migrations
SOUTH_MIGRATION_MODULES = {
'easy_thumbnails': 'easy_thumbnails.south_migrations',
}