[snowy] Add a preferences page, wire everything up



commit 6ce4851707515dff6139e95c4b827c9236641afe
Author: Brad Taylor <brad getcoded net>
Date:   Thu Jul 23 14:53:23 2009 -0400

    Add a preferences page, wire everything up
    
    This page will allow users to select their language and have it persist, and
    modify their password.

 accounts/forms.py                            |    7 ++++
 accounts/middleware.py                       |   27 ++++++++++++++
 accounts/models.py                           |   45 +++++++++++++++++++++++
 accounts/templates/accounts/preferences.html |   40 ++++++++++++++++++++
 accounts/urls.py                             |    3 ++
 accounts/views.py                            |   50 ++++++++++++++++++++++++++
 notes/admin.py                               |    5 ++-
 notes/models.py                              |   22 +-----------
 settings.py                                  |    3 +-
 templates/base.html                          |    2 +-
 10 files changed, 179 insertions(+), 25 deletions(-)
---
diff --git a/accounts/forms.py b/accounts/forms.py
index ded70df..e662620 100644
--- a/accounts/forms.py
+++ b/accounts/forms.py
@@ -67,3 +67,10 @@ class RegistrationFormUniqueUser(RegistrationFormUniqueEmail):
             raise forms.ValidationError(_(u'Your password must be at least 6 characters long.'))
 
         return password
+
+from snowy.accounts.models import UserProfile
+
+class InternationalizationForm(forms.ModelForm):
+    class Meta:
+        model = UserProfile
+        fields = ('language',)
diff --git a/accounts/middleware.py b/accounts/middleware.py
new file mode 100644
index 0000000..963854f
--- /dev/null
+++ b/accounts/middleware.py
@@ -0,0 +1,27 @@
+#
+# Copyright (c) 2009 Brad Taylor <brad getcoded net>
+#
+# This program 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.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+from django.middleware.common import CommonMiddleware
+from django.utils import translation
+
+class LocaleMiddleware():
+    def process_view(self, request, view_func, view_args, view_kwargs):
+        if request.user.is_authenticated():
+            profile = request.user.get_profile()
+            if profile.language:
+                translation.activate(profile.language)
+        return None
diff --git a/accounts/models.py b/accounts/models.py
new file mode 100644
index 0000000..15338bf
--- /dev/null
+++ b/accounts/models.py
@@ -0,0 +1,45 @@
+#
+# Copyright (c) 2009 Brad Taylor <brad getcoded net>
+#
+# This program 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.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+from django.utils.translation import ugettext_lazy as _
+from django.db.models.signals import post_save
+from django.contrib.auth.models import User
+from django.conf import settings
+from django.db import models
+
+import uuid
+
+class UserProfile(models.Model):
+    def _create_uuid():
+        return str(uuid.uuid4())
+
+    user = models.ForeignKey(User, unique=True)
+    latest_sync_rev = models.IntegerField(default=-1)
+    current_sync_uuid = models.CharField(max_length=36, default=_create_uuid)
+    language = models.CharField(max_length=5, choices=settings.LANGUAGES,
+                                verbose_name=_(u'Application Language'),
+                                null=True, blank=True)
+
+def _create_profile(sender, instance, created, **kwargs):
+    """
+    Create a UserProfile object in response to a new User being created.
+    """
+    if not created: return
+    UserProfile.objects.create(user=instance)
+
+post_save.connect(_create_profile, sender=User,
+                  dispatch_uid='django.contrib.auth.models.User')
diff --git a/accounts/templates/accounts/preferences.html b/accounts/templates/accounts/preferences.html
new file mode 100644
index 0000000..cc28b38
--- /dev/null
+++ b/accounts/templates/accounts/preferences.html
@@ -0,0 +1,40 @@
+{% extends "site_base.html" %}
+
+{% load i18n %}
+
+{% block content %}
+<h1>{% trans "Preferences" %}</h1>
+<h3>{% trans "Change your password" %}</h3>
+<form method="POST">
+    <table class="input-form">
+    {{ password_form.as_table }}
+        <tfoot>
+            <tr>
+                <th></th>
+                <td>
+                    <input type="submit" value="{% trans "Save" %}"/>
+                </td>
+            </tr>
+        </tfoot>
+    </table>
+    <input type="hidden" name="password_form" value="1" />
+</form>
+
+<h3>{% trans "Internationalization" %}</h3>
+<form method="POST">
+    <table class="input-form">
+    {{ i18n_form.as_table }}
+        <tfoot>
+            <tr>
+                <th></th>
+                <td>
+                    <input type="submit" value="{% trans "Save" %}"/>
+                </td>
+            </tr>
+        </tfoot>
+    </table>
+    <input type="hidden" name="i18n_form" value="1" />
+</form>
+
+{#<h3>{% trans "Registered Applications" %}</h3>#}
+{% endblock %}
diff --git a/accounts/urls.py b/accounts/urls.py
index f39f538..e9828ec 100644
--- a/accounts/urls.py
+++ b/accounts/urls.py
@@ -25,6 +25,9 @@ from registration.views import activate
 from registration.views import register
 
 urlpatterns = patterns('',
+    url(r'^preferences/$', 'snowy.accounts.views.accounts_preferences',
+        name='preferences'),
+
     # Registration URLs
     url(r'^activate/(?P<activation_key>\w+)/$', activate, name='registration_activate'),
     url(r'^login/$', auth_views.login, {'template_name': 'registration/login.html'},
diff --git a/accounts/views.py b/accounts/views.py
new file mode 100644
index 0000000..e4fedd4
--- /dev/null
+++ b/accounts/views.py
@@ -0,0 +1,50 @@
+#
+# Copyright (c) 2009 Brad Taylor <brad getcoded net>
+#
+# This program 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.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+from django.contrib.auth.forms import UserChangeForm, PasswordChangeForm
+from django.contrib.auth.decorators import login_required
+from django.shortcuts import render_to_response
+from django.http import HttpResponseRedirect
+from django.template import RequestContext
+from django.conf import settings
+
+from snowy.accounts.forms import InternationalizationForm
+
+ login_required
+def accounts_preferences(request, template_name='accounts/preferences.html'):
+    user = request.user
+    profile = user.get_profile()
+
+    if 'password_form' in request.POST:
+        password_form = PasswordChangeForm(user, data=request.POST)
+        if password_form.is_valid():
+            password_form.save()
+    else:
+        password_form = PasswordChangeForm(user)
+
+    if 'i18n_form' in request.POST:
+        i18n_form = InternationalizationForm(request.POST, instance=profile)
+        if i18n_form.is_valid():
+            print 'Internationalization form is valid!'
+            i18n_form.save()
+    else:
+        i18n_form = InternationalizationForm(instance=profile)
+
+    return render_to_response(template_name,
+                              {'user': user, 'i18n_form': i18n_form,
+                               'password_form': password_form},
+                              context_instance=RequestContext(request))
diff --git a/notes/admin.py b/notes/admin.py
index 2c7f587..6654a55 100644
--- a/notes/admin.py
+++ b/notes/admin.py
@@ -15,9 +15,10 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
-from django.contrib import admin
+from snowy.accounts.models import UserProfile
+from snowy.notes.models import Note, NoteTag
 from reversion.admin import VersionAdmin
-from snowy.notes.models import *
+from django.contrib import admin
 
 class NoteAdmin(VersionAdmin):
     list_display = ('created', 'author', 'title')
diff --git a/notes/models.py b/notes/models.py
index 8aa48e0..31b62cd 100644
--- a/notes/models.py
+++ b/notes/models.py
@@ -15,9 +15,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
-import uuid
-
-from django.db.models.signals import post_save, pre_save
+from django.db.models.signals import pre_save
 from django.contrib.auth.models import User
 from django.db import models
 
@@ -102,21 +100,3 @@ def _update_is_notebook(sender, instance, **kwargs):
 pre_save.connect(_update_is_notebook, sender=NoteTag,
                  dispatch_uid='snowy.notes.models.NoteTag')
 
-
-class UserProfile(models.Model):
-    def _create_uuid():
-        return str(uuid.uuid4())
-
-    user = models.ForeignKey(User, unique=True)
-    latest_sync_rev = models.IntegerField(default=-1)
-    current_sync_uuid = models.CharField(max_length=36, default=_create_uuid)
-
-def _create_profile(sender, instance, created, **kwargs):
-    """
-    Create a UserProfile object in response to a new User being created.
-    """
-    if not created: return
-    UserProfile.objects.create(user=instance)
-
-post_save.connect(_create_profile, sender=User,
-                  dispatch_uid='django.contrib.auth.models.User')
diff --git a/settings.py b/settings.py
index ddfdfc1..da2295e 100644
--- a/settings.py
+++ b/settings.py
@@ -86,6 +86,7 @@ MIDDLEWARE_CLASSES = (
     'django.contrib.csrf.middleware.CsrfResponseMiddleware',
     'django.contrib.sessions.middleware.SessionMiddleware',
     'django.middleware.locale.LocaleMiddleware',
+    'snowy.accounts.middleware.LocaleMiddleware',
     'django.contrib.auth.middleware.AuthenticationMiddleware',
     'django.middleware.transaction.TransactionMiddleware',
     'reversion.middleware.RevisionMiddleware',
@@ -135,7 +136,7 @@ SNOWY_LIST_MAX_NOTES = 18
 
 ACCOUNT_ACTIVATION_DAYS = 15
 
-AUTH_PROFILE_MODULE = 'notes.UserProfile'
+AUTH_PROFILE_MODULE = 'accounts.UserProfile'
 
 # local_settings.py can be used to override environment-specific settings
 # like database and email that differ between development and production.
diff --git a/templates/base.html b/templates/base.html
index 7671f6a..1ee011d 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -31,7 +31,7 @@
                 <td id="header-auth">
 {% if user.is_authenticated %}
                     <h3>{{ user }}</h3>
-                    <p><a href="">{% trans "preferences" %}</a> / <a href="{% url django.contrib.auth.views.logout %}">{% trans "log out" %}</a></p>
+                    <p><a href="{% url preferences %}">{% trans "preferences" %}</a> / <a href="{% url django.contrib.auth.views.logout %}">{% trans "log out" %}</a></p>
 {% else %}
                     <p>{% trans "hello stranger! care to " %}<a href="{% url django.contrib.auth.views.login %}">{% trans "log in" %}</a>{% trans "?" %}</p>
                     <p><small>{% trans "not a member yet?" %} <a href="{% url registration.views.register %}">{% trans "Sign up." %}</a></small></p>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]