Add Google Analytics support to Site Settings. The reason I created additional SettingsValidationForm is because you cannot inherit from Form that has already defined Meta class, so it's sort of workaround for that. I didn't want to have same validation functions in both Form classes.
authorPawel Solyga <Pawel.Solyga@gmail.com>
Wed, 22 Oct 2008 16:21:50 +0000
changeset 405 f3525c1288ed
parent 404 44223e50e1fc
child 406 cc603a815cad
Add Google Analytics support to Site Settings. The reason I created additional SettingsValidationForm is because you cannot inherit from Form that has already defined Meta class, so it's sort of workaround for that. I didn't want to have same validation functions in both Form classes. Patch by: Pawel Solyga Review by: to-be-reviewed
app/soc/logic/site/map.py
app/soc/models/site_settings.py
app/soc/templates/soc/base.html
app/soc/templates/soc/site/ga.html
app/soc/views/helper/responses.py
app/soc/views/settings.py
app/soc/views/site/settings.py
--- a/app/soc/logic/site/map.py	Wed Oct 22 06:20:02 2008 +0000
+++ b/app/soc/logic/site/map.py	Wed Oct 22 16:21:50 2008 +0000
@@ -108,7 +108,7 @@
 site_settings_edit = page.Page(
   page.Url(
     r'^site/settings/edit$',
-    'soc.views.settings.edit',
+    'soc.views.site.settings.edit',
     kwargs={
       'path': models.site_settings.logic.DEF_SITE_SETTINGS_PATH,
       'logic': models.site_settings.logic,
--- a/app/soc/models/site_settings.py	Wed Oct 22 06:20:02 2008 +0000
+++ b/app/soc/models/site_settings.py	Wed Oct 22 16:21:50 2008 +0000
@@ -21,12 +21,22 @@
 ]
 
 
+from google.appengine.ext import db
+
+from django.utils.translation import ugettext_lazy
+
 import soc.models.home_settings
 
 
 class SiteSettings(soc.models.home_settings.HomeSettings):
   """Model of a SiteSettings, which stores per site configuration."""
-  # there is currently no site-specific configuration that is different from
-  # other /home page configuration (but this will change...)
-  pass 
 
+  #: Valid Google Analytics tracking number, if entered every page
+  #: is going to have Google Analytics JS initialization code in 
+  #: the footer with the given tracking number.
+  ga_tracking_no = db.StringProperty(verbose_name=ugettext_lazy('Google Analytics'))
+  ga_tracking_no.help_text = ugettext_lazy(
+      'Valid Google Analytics tracking number. If the number is '
+      'entered every page is going to have Google Analytics '
+      'initialization code in footer.')
+
--- a/app/soc/templates/soc/base.html	Wed Oct 22 06:20:02 2008 +0000
+++ b/app/soc/templates/soc/base.html	Wed Oct 22 16:21:50 2008 +0000
@@ -146,9 +146,10 @@
 </p>
 	{% endblock %}
    </div>
-
-	
    <div id="footer" dir="ltr">
+    {% if ga_tracking_no %}
+    {% include 'soc/site/ga.html' %}
+    {% endif %}
     <div class="text">
 	{% block footer %}
 &copy;2008 Google -
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/soc/templates/soc/site/ga.html	Wed Oct 22 16:21:50 2008 +0000
@@ -0,0 +1,21 @@
+{% comment %}
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+{% endcomment %}
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+_uacct="{{ ga_tracking_no }}"; // site-wide Google Analytics tracking
+_uanchor=1;
+_uff=0;
+urchinTracker();
+</script>
--- a/app/soc/views/helper/responses.py	Wed Oct 22 06:20:02 2008 +0000
+++ b/app/soc/views/helper/responses.py	Wed Oct 22 16:21:50 2008 +0000
@@ -29,6 +29,7 @@
 from django.template import loader
 
 from soc.logic import system
+from soc.logic.models import site_settings as settings_logic
 from soc.logic.site import id_user
 from soc.logic.site import sidebar
 from soc.views import helper
@@ -107,7 +108,13 @@
   context['sign_out'] = users.create_logout_url(request.path)
   context['sidebar_menu_html'] = str(html_menu.UlMenu(
       sidebar.buildSidebar(**context)))
-
+      
+  site_settings = settings_logic.logic.getFromFields(
+      path=settings_logic.logic.DEF_SITE_SETTINGS_PATH)
+  
+  if site_settings and site_settings.ga_tracking_no:
+    context['ga_tracking_no'] = site_settings.ga_tracking_no
+  
   return context
 
 
--- a/app/soc/views/settings.py	Wed Oct 22 06:20:02 2008 +0000
+++ b/app/soc/views/settings.py	Wed Oct 22 16:21:50 2008 +0000
@@ -48,19 +48,12 @@
 import soc.views.out_of_band
 
 
-class SettingsForm(helper.forms.DbModelForm):
+class SettingsValidationForm(helper.forms.DbModelForm):
   """Django form displayed when creating or editing Settings.
+  
+  This form includes validation functions for Settings fields.
   """
 
-  class Meta:
-    """Inner Meta class that defines some behavior for the form.
-    """
-    #: db.Model subclass for which the form will gather information
-    model = soc.models.home_settings.HomeSettings
-
-    #: list of model fields which will *not* be gathered by the form
-    exclude = ['inheritance_line', 'home']
-
   def clean_feed_url(self):
     feed_url = self.cleaned_data.get('feed_url')
 
@@ -74,6 +67,20 @@
     return feed_url
 
 
+class SettingsForm(SettingsValidationForm):
+  """Django form displayed when creating or editing Settings.
+  """
+
+  class Meta:
+    """Inner Meta class that defines some behavior for the form.
+    """
+    #: db.Model subclass for which the form will gather information
+    model = soc.models.home_settings.HomeSettings
+
+    #: list of model fields which will *not* be gathered by the form
+    exclude = ['inheritance_line', 'home']
+
+
 class DocSelectForm(helper.forms.DbModelForm):
   """Django form displayed to select a Document.
   """
@@ -99,6 +106,7 @@
 
 @decorators.view
 def edit(request, page=None, path=None, logic=models.home_settings.logic,
+         settings_form_class=SettingsForm,
          template=DEF_HOME_EDIT_TMPL):
   """View for authorized User to edit contents of a home page.
 
@@ -106,6 +114,9 @@
     request: the standard django request object.
     page: a soc.logic.site.page.Page object which is abstraction that
       combines a Django view with sidebar menu info
+    path: path that is used to uniquely identify settings
+    logic: settings logic object
+    settings_form_class:
     template: the template path to use for rendering the template.
 
   Returns:
@@ -128,11 +139,17 @@
   home_doc = None
 
   if request.method == 'POST':
-    settings_form = SettingsForm(request.POST)
+    settings_form = settings_form_class(request.POST)
     doc_select_form = DocSelectForm(request.POST)
     
     if doc_select_form.is_valid() and settings_form.is_valid():
-      fields = {'feed_url': settings_form.cleaned_data.get('feed_url')}
+      fields = {}      
+      
+      # Ask for all the fields and pull them out 
+      for field in settings_form.cleaned_data:
+        value = settings_form.cleaned_data.get(field)
+        fields[field] = value
+
       partial_path = doc_select_form.cleaned_data.get('partial_path')
       link_name = doc_select_form.cleaned_data.get('link_name')
 
@@ -157,7 +174,7 @@
 
     if settings:
       # populate form with the existing HomeSettings entity
-      settings_form = SettingsForm(instance=settings)
+      settings_form = settings_form_class(instance=settings)
 
       # check if ReferenceProperty to home Document is valid
       try:
@@ -173,7 +190,7 @@
         doc_select_form = DocSelectForm()
     else:
       # no SiteSettings entity exists for this key_name, so show a blank form
-      settings_form = SettingsForm()
+      settings_form = settings_form_class()
       doc_select_form = DocSelectForm()
 
   context.update({'settings_form': settings_form,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/soc/views/site/settings.py	Wed Oct 22 16:21:50 2008 +0000
@@ -0,0 +1,69 @@
+#!/usr/bin/python2.5
+#
+# Copyright 2008 the Melange authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Site Settings views.
+
+edit: settings view for authorized Developers, Administrators, etc.
+"""
+
+__authors__ = [
+  '"Pawel Solyga" <pawel.solyga@gmail.com>',
+  ]
+
+
+from soc.logic import models
+from soc.views import settings as settings_views
+from soc.views.helper import decorators
+
+import soc.logic.models.site_settings
+import soc.models.site_settings
+
+
+class SiteSettingsForm(settings_views.SettingsValidationForm):
+  """Django form displayed when creating or editing Site Settings.
+  """
+
+  class Meta:
+    """Inner Meta class that defines some behavior for the form.
+    """
+    #: db.Model subclass for which the form will gather information
+    model = soc.models.site_settings.SiteSettings
+
+    #: list of model fields which will *not* be gathered by the form
+    exclude = ['inheritance_line', 'home']
+
+
+@decorators.view
+def edit(request, page=None, path=None, logic=models.site_settings.logic,
+         settings_form_class=SiteSettingsForm,
+         template=settings_views.DEF_HOME_EDIT_TMPL):
+  """View for authorized User to edit contents of a Site Settings page.
+
+  Args:
+    request: the standard django request object.
+    page: a soc.logic.site.page.Page object which is abstraction that
+      combines a Django view with sidebar menu info
+    path: path that is used to uniquely identify settings
+    logic: settings logic object
+    settings_form_class: class which should be used as Site Settings Form
+    template: the template path to use for rendering the template.
+
+  Returns:
+    A subclass of django.http.HttpResponse with generated template.
+  """
+  return settings_views.edit(request, page=page, path=path, logic=logic,
+                             settings_form_class=SiteSettingsForm,
+                             template=template)
\ No newline at end of file