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
--- 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 %}
©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