Mercurial > personas_backend
changeset 127:382af80db050
Rename of temp dir to personasbackend
author | Atul Varma <varmaa@toolness.com> |
---|---|
date | Wed, 02 Apr 2008 11:59:58 -0700 |
parents | cb128e025ae9 |
children | 9bcc77e37c19 |
files | PersonasBackendTemp/__init__.py PersonasBackendTemp/manage.py PersonasBackendTemp/personas/__init__.py PersonasBackendTemp/personas/ajax.py PersonasBackendTemp/personas/fixtures/initial_data.xml PersonasBackendTemp/personas/forms.py PersonasBackendTemp/personas/json_feeds.py PersonasBackendTemp/personas/models.py PersonasBackendTemp/personas/sections.py PersonasBackendTemp/personas/templates/personas/base.html PersonasBackendTemp/personas/templates/personas/edit.html PersonasBackendTemp/personas/templates/personas/home.html PersonasBackendTemp/personas/templates/personas/legacy_persona.xul PersonasBackendTemp/personas/templates/personas/list.html PersonasBackendTemp/personas/templates/personas/logged_out.html PersonasBackendTemp/personas/templates/personas/login.html PersonasBackendTemp/personas/templates/personas/todo.html PersonasBackendTemp/personas/tests.py PersonasBackendTemp/personas/urls.py PersonasBackendTemp/personas/views.py PersonasBackendTemp/settings.py PersonasBackendTemp/urls.py PersonasBackendTemp/utils.py PersonasBackendTemp/weaveproxyauth.py personasbackend/__init__.py personasbackend/manage.py personasbackend/personas/__init__.py personasbackend/personas/ajax.py personasbackend/personas/fixtures/initial_data.xml personasbackend/personas/forms.py personasbackend/personas/json_feeds.py personasbackend/personas/models.py personasbackend/personas/sections.py personasbackend/personas/templates/personas/base.html personasbackend/personas/templates/personas/edit.html personasbackend/personas/templates/personas/home.html personasbackend/personas/templates/personas/legacy_persona.xul personasbackend/personas/templates/personas/list.html personasbackend/personas/templates/personas/logged_out.html personasbackend/personas/templates/personas/login.html personasbackend/personas/templates/personas/todo.html personasbackend/personas/tests.py personasbackend/personas/urls.py personasbackend/personas/views.py personasbackend/settings.py personasbackend/urls.py personasbackend/utils.py personasbackend/weaveproxyauth.py |
diffstat | 44 files changed, 1444 insertions(+), 1444 deletions(-) [+] |
line wrap: on
line diff
--- a/PersonasBackendTemp/manage.py Wed Apr 02 11:59:36 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -#!/usr/bin/env python -from django.core.management import execute_manager -try: - import settings # Assumed to be in the same directory. -except ImportError: - import sys - sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__) - sys.exit(1) - -if __name__ == "__main__": - execute_manager(settings)
--- a/PersonasBackendTemp/personas/ajax.py Wed Apr 02 11:59:36 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -from django.http import HttpResponse -from django.shortcuts import get_object_or_404 - -from PersonasBackend.personas import models - -def report_selection( request, persona_id ): - persona = get_object_or_404( models.Persona, id=persona_id ) - persona.popularity += 1 - persona.save() - return HttpResponse()
--- a/PersonasBackendTemp/personas/fixtures/initial_data.xml Wed Apr 02 11:59:36 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<django-objects version="1.0"><object pk="1" model="personas.category"><field type="CharField" name="name">Other</field></object><object pk="2" model="personas.category"><field type="CharField" name="name">Geometric</field></object><object pk="3" model="personas.category"><field type="CharField" name="name">Sports</field></object><object pk="4" model="personas.category"><field type="CharField" name="name">Scenery</field></object><object pk="5" model="personas.category"><field type="CharField" name="name">Nature</field></object><object pk="6" model="personas.category"><field type="CharField" name="name">Holidays</field></object><object pk="7" model="personas.category"><field type="CharField" name="name">Foxkeh</field></object><object pk="8" model="personas.category"><field type="CharField" name="name">Firefox</field></object><object pk="1" model="personas.persona"><field type="CharField" name="name">Firefox Logo</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">8</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=firefox_b</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="2" model="personas.persona"><field type="CharField" name="name">Firefox Flicks</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">8</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=firefox_flicks</field><field type="CharField" name="text_color">#FFFFFF</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="3" model="personas.persona"><field type="CharField" name="name">Mozilla Classic</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">8</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=mozilla_classic</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="4" model="personas.persona"><field type="CharField" name="name">Foxkeh Straw</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">7</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=foxkeh_straw</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="5" model="personas.persona"><field type="CharField" name="name">Foxkeh Hanami</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">7</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=foxkeh_hanami</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="6" model="personas.persona"><field type="CharField" name="name">Foxkeh Hinimatsuri</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">7</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=foxkeh_hinimatsuri</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="7" model="personas.persona"><field type="CharField" name="name">Foxkeh Kodomo No Hi</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">7</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=foxkeh_kodomo_no_hi</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="8" model="personas.persona"><field type="CharField" name="name">Foxkeh Setsubun</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">7</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=foxkeh_setsubun</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="9" model="personas.persona"><field type="CharField" name="name">Foxkeh Giant Butterbur</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">7</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=foxkeh_butterbur</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="10" model="personas.persona"><field type="CharField" name="name">Foxkeh Tanabata</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">7</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=foxkeh_tanabata</field><field type="CharField" name="text_color">#FFFFFF</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="11" model="personas.persona"><field type="CharField" name="name">Viva Firefox</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">8</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=viva</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="12" model="personas.persona"><field type="CharField" name="name">Developer Kit</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">8</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=kit</field><field type="CharField" name="text_color">#FFFFFF</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="13" model="personas.persona"><field type="CharField" name="name">Tranquility</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">5</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=tranquility</field><field type="CharField" name="text_color">#FFFFFF</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="14" model="personas.persona"><field type="CharField" name="name">California Sunset</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">4</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=california_sunset</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="15" model="personas.persona"><field type="CharField" name="name">Wood Paneling</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">1</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=wood_paneling</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="16" model="personas.persona"><field type="CharField" name="name">Hearts</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">1</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=hearts</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="17" model="personas.persona"><field type="CharField" name="name">Blue Spheres</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">1</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=blue_spheres</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="18" model="personas.persona"><field type="CharField" name="name">Les Diablerets</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">4</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=les_diablerets</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="19" model="personas.persona"><field type="CharField" name="name">Seagull</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">4</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=seagull</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="20" model="personas.persona"><field type="CharField" name="name">Verdelet</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">4</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=verdelet</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="21" model="personas.persona"><field type="CharField" name="name">Green Wave</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">1</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=green_wave</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="22" model="personas.persona"><field type="CharField" name="name">Golf</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">3</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=golf</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="23" model="personas.persona"><field type="CharField" name="name">Basketball</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">3</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=bball</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="24" model="personas.persona"><field type="CharField" name="name">Antique Wallpaper</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">1</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=antique_wallpaper</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="25" model="personas.persona"><field type="CharField" name="name">Bamboo</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">5</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=bamboo</field><field type="CharField" name="text_color">#FFFFFF</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="26" model="personas.persona"><field type="CharField" name="name">Plaid</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">2</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=plaid</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="27" model="personas.persona"><field type="CharField" name="name">Soccer</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">3</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=soccer</field><field type="CharField" name="text_color">#FFFFFF</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="28" model="personas.persona"><field type="CharField" name="name">Suede</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">1</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=suede</field><field type="CharField" name="text_color">#FFFFFF</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="29" model="personas.persona"><field type="CharField" name="name">Aquarium</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">5</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=aquarium</field><field type="CharField" name="text_color">#FFFFFF</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="30" model="personas.persona"><field type="CharField" name="name">Dialogonal Lines</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">2</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=diagonal_lines</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="31" model="personas.persona"><field type="CharField" name="name">Dots</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">2</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=dots</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="32" model="personas.persona"><field type="CharField" name="name">Golden Gate Bridge</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">4</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=golden_gate_bridge</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="33" model="personas.persona"><field type="CharField" name="name">Grass</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">5</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=grass</field><field type="CharField" name="text_color">#FFFFFF</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="34" model="personas.persona"><field type="CharField" name="name">Foxkeh Green Winter</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">7</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=foxkeh_green_winter</field><field type="CharField" name="text_color">#FFFFFF</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="35" model="personas.persona"><field type="CharField" name="name">Jellyfish</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">5</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=jellyfish</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="36" model="personas.persona"><field type="CharField" name="name">Yosemite</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">4</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=yosemite</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="37" model="personas.persona"><field type="CharField" name="name">Snowman</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">6</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=snowman</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="38" model="personas.persona"><field type="CharField" name="name">Snowflakes</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">6</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=snowflakes</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="39" model="personas.persona"><field type="CharField" name="name">Reindeer</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">6</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=reindeer</field><field type="CharField" name="text_color">#FFFFFF</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="40" model="personas.persona"><field type="CharField" name="name">Foxkeh Canoe</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">7</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=foxkeh_canoe</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="41" model="personas.persona"><field type="CharField" name="name">Foxkeh Helloween</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">7</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=foxkeh_helloween</field><field type="CharField" name="text_color">#FFFFFF</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="42" model="personas.persona"><field type="CharField" name="name">Foxkeh Susuki</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">7</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=foxkeh_susuki</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="43" model="personas.persona"><field type="CharField" name="name">Foxkeh Hanabi</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">7</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=foxkeh_hanabi</field><field type="CharField" name="text_color">#FFFFFF</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="44" model="personas.persona"><field type="CharField" name="name">Paper</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">1</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=paper</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="45" model="personas.persona"><field type="CharField" name="name">Winter</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">6</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=winter</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="46" model="personas.persona"><field type="CharField" name="name">Leather</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">1</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=leather</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="47" model="personas.persona"><field type="CharField" name="name">Niagra Falls</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">4</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=niagra_falls</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="48" model="personas.persona"><field type="CharField" name="name">Groovy Blue</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">1</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=groovy_blue</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="49" model="personas.persona"><field type="CharField" name="name">Groovy Hearts</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">1</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=groovy_hearts</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="50" model="personas.persona"><field type="CharField" name="name">Groovy Orange</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">1</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=groovy_orange</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="51" model="personas.persona"><field type="CharField" name="name">Groovy Pink</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">1</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=groovy_pink</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object></django-objects>
--- a/PersonasBackendTemp/personas/forms.py Wed Apr 02 11:59:36 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -import django.newforms as forms -from PersonasBackend.personas import models - -class PersonaForm( forms.ModelForm ): - """ - Form given to normal users who don't have the permission to - publish Personas. - """ - - class Meta: - model = models.Persona - exclude = ["owner", "date_published", "popularity", "status"] - - agree_to_terms = forms.BooleanField( - label = "I agree to the terms of use.", - # TODO: setting required to True doesn't seem to have any effect, - # but the Django docs say it should ensure that the checkbox - # is filled out. - required = True, - help_text = ("Terms of use: I agree that Mozilla is providing " - "a service by hosting the " - "content I am submitting, and that they are in no " - "way responsible for any damages that occur as " - "a result of hosting said content.") - ) - - def _color_cleaner( self, field ): - models.ensure_color_is_valid( - self.cleaned_data[field], - error_class = forms.ValidationError - ) - return self.cleaned_data[field] - - def clean_text_color( self ): - return self._color_cleaner( "text_color" ) - - def clean_accent_color( self ): - return self._color_cleaner( "accent_color" ) - - def clean( self ): - if not self.cleaned_data["agree_to_terms"]: - raise forms.ValidationError( - "You must agree to the terms of service to " - "submit your Persona." - ) - - return self.cleaned_data
--- a/PersonasBackendTemp/personas/json_feeds.py Wed Apr 02 11:59:36 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -from django.http import HttpResponse -from django.utils import simplejson - -from PersonasBackend.personas import models - -NEW_MENU_ID = "personas-new-menu" -POPULAR_MENU_ID = "personas-popular-menu" - -def _makeJsonResponse( obj ): - json = simplejson.dumps( obj, indent=4 ) - response = HttpResponse( json ) - response["Content-Type"] = "text/plain" - return response - -def categories( request ): - categoryDicts = [ - {"label": "Most Popular", "id" : POPULAR_MENU_ID, - "type" : "list", "parent" : "top" }, - {"label": "Recent", "id" : "personas-recent-menu", - "type" : "recent", "parent" : "top" }, - {"label": "New", "id" : NEW_MENU_ID, - "type" : "list", "parent" : "top" }, - {"label": "All", "id" : "personas-category-menu", - "type" : "category", "parent" : "top" }, - ] - - for category in models.Category.objects.all(): - categoryDicts.append( - {"label" : category.name, - "id" : category.json_id, - "type" : "list", - "parent" : "personas-category-menu"} - ) - - return _makeJsonResponse( {"categories" : categoryDicts} ) - -def personas( request ): - personaDicts = [] - - isPopular = {} - isNew = {} - - published = models.Persona.objects.filter( status="published" ) - - for persona in published.order_by( "-popularity" )[:10]: - isPopular[persona.id] = True - - for persona in published.order_by( "-date_published" )[:10]: - isNew[persona.id] = True - - for persona in published: - categories = [persona.category.json_id] - if persona.id in isPopular: - categories.append( POPULAR_MENU_ID ) - if persona.id in isNew: - categories.append( NEW_MENU_ID ) - - personaDicts.append( - {"label" : persona.name, - "id" : persona.json_id, - "textColor" : persona.text_color, - "accentColor" : persona.accent_color, - "baseURL" : persona.resolved_url, - "menu" : ",".join( categories ), - "preview" : "yes"} - ) - - return _makeJsonResponse( {"personas" : personaDicts} )
--- a/PersonasBackendTemp/personas/models.py Wed Apr 02 11:59:36 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,604 +0,0 @@ -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (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.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is PersonasBackend. -# -# The Initial Developer of the Original Code is Mozilla. -# Portions created by the Initial Developer are Copyright (C) 2008 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Atul Varma <atul@mozilla.org> -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -""" -models.py - -This module contains the models for the Personas application. - -Note that changes to Personas are automatically revision-controlled. -Among other things, this allows for: - - (A) A humane user interface that supports undo operations. - - (B) A workflow that allows for Personas to be changed by a submitter - and reviewed while the original, unchanged Persona remains - published and accessible by clients. -""" - -import datetime - -from django.db import models -from django.core.urlresolvers import reverse -from django.contrib.auth.models import User -from django.core.validators import ValidationError - -from PersonasBackend.utils import make_absolute_url - -MAX_COLOR_LENGTH = 7 - -def parse_personas_view_url( url ): - """ - TODO: Document this. - - Examples: - - >>> parse_personas_view_url( "http://personas-view/blargy?thing=blarg" ) - {'kwargs': {'thing': 'blarg'}, 'view': 'blargy'} - - >>> parse_personas_view_url( "http://porsonas-view/blargy?thing=blarg" ) - """ - - if not url.startswith( "http://personas-view/" ): - return None - - import urlparse - import cgi - - _, _, path, _, query, _ = urlparse.urlparse( url ) - view = path[1:] - kwargs = cgi.parse_qs( query ) - - # It is completely ridiculous that we have to do this, but - # apparently we do, because django's reverse() doesn't like being - # passed dictionaries with unicode keys. - string_kwargs = {} - for key in kwargs: - string_kwargs[str(key)] = str(kwargs[key][0]) - - return {'view':view, 'kwargs':string_kwargs} - -def ensure_color_is_valid( color, - error_class = ValidationError ): - """ - Given a color string, raises a ValidationError if the color isn't - formatted properly. - - Examples: - - >>> ensure_color_is_valid('') - - >>> ensure_color_is_valid('blah') - Traceback (most recent call last): - ... - ValidationError: [u"The color must start with a '#'."] - - >>> ensure_color_is_valid('#aaaaaaa') - Traceback (most recent call last): - ... - ValidationError: [u'The color is too long.'] - - >>> ensure_color_is_valid('#aaaaa') - Traceback (most recent call last): - ... - ValidationError: [u'The color is too short.'] - - >>> ensure_color_is_valid('#aaazaa') - Traceback (most recent call last): - ... - ValidationError: [u"The character 'z' isn't valid."] - - >>> ensure_color_is_valid('#aaaaaa') - >>> ensure_color_is_valid('#FFFF11') - """ - - HEX_CHARS = "0123456789abcdef" - - if not color: - return - - if not color.startswith("#"): - raise error_class( "The color must start with a '#'." ) - if len(color) > MAX_COLOR_LENGTH: - raise error_class( "The color is too long." ) - if len(color) < MAX_COLOR_LENGTH: - raise error_class( "The color is too short." ) - for char in color.lower()[1:MAX_COLOR_LENGTH]: - if char not in HEX_CHARS: - raise error_class( "The character '%s' isn't valid." % char ) - -class Category(models.Model): - """ - Represents a Personas category; every Persona can be assigned one, - and only one, category. - """ - - class Admin: - pass - - class Meta: - verbose_name_plural = "categories" - - name = models.CharField( - "Category name", - max_length=50, - unique=True, - ) - - def __str__(self): - return self.name - - def _get_json_id( self ): - return "personas-category-%d" % self.id - - json_id = property( _get_json_id ) - -class Persona(models.Model): - """ - Encapsulates the most recent revision of a Persona. - """ - - class Admin: - list_display = ["name", "date_updated", "status"] - - class Meta: - permissions = ( - ("can_publish", "Can publish"), - ) - - MAX_NAME_LENGTH = 50 - - name = models.CharField( - max_length=MAX_NAME_LENGTH, - blank=False, - ) - - owner = models.ForeignKey( - User, - help_text=("The user who owns this persona can make " - "changes to it."), - related_name="owned_personas", - # TODO: Consider making this null=False. Keeping it true - # makes it easier to write tests, though. - null=True, - blank=True, - ) - - category = models.ForeignKey( - Category, - related_name="personas", - null=False, - ) - - description = models.TextField( - help_text = "HTML is allowed.", - blank=False, - ) - - url = models.URLField( - "Persona URL", - help_text=("URL for the content that will be placed behind " - "the browser's chrome."), - verify_exists=False, - blank=False, - ) - - def __get_resolved_url(self): - viewinfo = parse_personas_view_url( self.url ) - if not viewinfo: - return self.url - else: - return make_absolute_url( reverse( - viewinfo['view'], - kwargs = viewinfo['kwargs'] - ) ) - - resolved_url = property(__get_resolved_url) - - text_color = models.CharField( - help_text=("The RGB color, as a #RRGGBB color hash, " - "of the color of text that will be displayed " - "on the persona."), - max_length=MAX_COLOR_LENGTH, - validator_list=[ensure_color_is_valid], - blank=True - ) - - accent_color = models.CharField( - help_text=("The RGB color, as a #RRGGBB color hash, " - "of the accent colors that will be displayed " - "on the persona."), - max_length=MAX_COLOR_LENGTH, - validator_list=[ensure_color_is_valid], - blank=True, - ) - - date_published = models.DateTimeField( - help_text=("The date that the Persona was last published."), - null=True, - editable=True, - ) - - date_updated = models.DateTimeField( - # This ensures that this field is updated with the current - # timestamp whenever the record is changed. - auto_now=True, - null=False, - editable=False, - ) - - updater = models.ForeignKey( - User, - help_text="The user who made this revision.", - related_name="changed_personas", - null=True, - editable=False - ) - - revision = models.PositiveIntegerField( - "Revision number", - help_text=("This number is incremented whenever the Persona " - "is changed."), - null=False, - editable=False, - ) - - popularity = models.PositiveIntegerField( - "Popularity", - help_text=("A number indicating how popular the Persona is; the " - "higher this value, the better."), - default=0, - null=False, - ) - - MAX_STATUS_LENGTH = 10 - - status = models.CharField( - max_length=MAX_STATUS_LENGTH, - choices=(("published", "Published"), - ("unpublished", "Unpublished"), - ("deleted", "Deleted")), - blank=False, - help_text=("Status of the Persona; can be deleted, published, " - "or unpublished (i.e., pending for review).") - ) - - def __str__(self): - return self.name - - # These are the properties of this record that are "versioned", - # i.e. tracked by built-in revision control when changed. - VERSIONED_PROPERTIES = ( - "name", - "owner", - "category", - "description", - "url", - "text_color", - "accent_color", - "status", - ) - - def __make_new_revision(self): - """ - Detect if any of our versioned properties have changed, and if - so, make a new revision. - """ - - original = Persona.objects.get(id=self.id) - - assert original.revision == self.revision - - delta = {} - for attr in self.VERSIONED_PROPERTIES: - origValue = getattr(original, attr) - newValue = getattr(self, attr) - if origValue != newValue: - delta[attr] = origValue - if delta: - rev = Revision( - revision_of = original, - date_updated = original.date_updated, - updater = original.updater, - revision = original.revision - ) - - for attr in delta: - setattr(rev, attr, delta[attr]) - setattr(rev, "has_%s" % attr, True) - rev.save() - - self.revision += 1 - - def save( self, updater=None ): - """ - Saves the object. If a versioned property is changed, a new - revision is generated automatically. - - Example: - - >>> p = Persona(name='Test Persona', - ... description='Thos is a test.', - ... url='http://blarg.com', - ... category=Category.objects.get(name='Other')) - >>> p.save() - >>> p.revision - 0 - >>> p.revisions.all() - [] - - >>> p.description = 'This is a test.' - >>> p.url = 'http://blarg2.com' - >>> p.save() - >>> p.revision - 1 - >>> p.revisions.all() - [<Revision: Test Persona - r0>] - >>> p.revisions.get(revision=0).description - u'Thos is a test.' - >>> p.revisions.get(revision=0).url - u'http://blarg.com' - """ - - if updater: - self.updater = updater - else: - # We were probably saved through the admin interface, - # which saves its own separate history of changes. - self.updater = None - - if self.id == None: - # We're a brand-new Persona. - self.revision = 0 - if not self.owner: - self.owner = self.updater - assert self.owner == self.updater - if not self.status: - if ( self.updater and - self.updater.has_perm( "personas.can_publish" ) ): - # If the person creating the Persona can publish - # Personas, mark this new Persona as published, by - # default. - self.status = "published" - else: - # Otherwise, mark this new Persona as unpublished by - # default. - self.status = "unpublished" - if self.status == "published": - self.date_published = datetime.datetime.now() - else: - # We're an existing Persona that's being modified. - - if self.updater: - if not self.can_user_edit( self.updater ): - # The user can't actually edit this Persona, reject - # the change. View logic should've prevented this - # from ever being the case, so we're going to be - # ungraceful here. - raise AssertionError( "User can't edit this persona." ) - - if ( self.status == "published" and - not self.updater.has_perm( "personas.can_publish" ) ): - # The Persona is currently published, but a user - # without publishing permissions has just changed it, - # so mark it as unpublished so an editor can review it - # before re-publishing it. - - self.status = "unpublished" - - original = Persona.objects.get(id=self.id) - - if ( (original.status != self.status) and - (self.status == "published") ): - self.date_published = datetime.datetime.now() - - self.__make_new_revision() - - super(Persona, self).save() - - def can_user_edit( self, user ): - """ - Returns whether the given User can edit this Persona. - """ - - return ( user.has_perm( "personas.can_publish" ) or - self.owner == user ) - - def _get_json_id( self ): - return "persona-%d" % self.id - - json_id = property( _get_json_id ) - -class Revision(models.Model): - """ - Represents an old revision of a Persona. - - This record only stores a "reverse delta" relative to the revision - that follows it; for instance, if a user changes a Persona at - revision 0 by modifying its description, then the Revision record - for revision 0 will contain only the description for the Persona - at that revision, since all other properties can be obtained by - looking at revision 1. In this way, the complete "picture" of - revision 0 can be reconstructed by starting at the record for - revision 0 and traveling to newer revisions until every field of - the Persona has been populated. - """ - - class Meta: - unique_together = (("revision_of", "revision"),) - ordering = ["revision"] - - # Auto-generated fields - - revision_of = models.ForeignKey( - Persona, - verbose_name="The Persona that this record is an old revision of", - related_name="revisions", - null=False, - ) - - date_updated = models.DateTimeField( - null=False, - ) - - updater = models.ForeignKey( - User, - related_name="previously_changed_revisions", - null=True, - ) - - revision = models.PositiveIntegerField( - null=False, - ) - - # Versioned fields - - for attr in Persona.VERSIONED_PROPERTIES: - locals()["has_%s" % attr] = models.BooleanField(default=False) - del attr - - name = models.CharField( - max_length=Persona.MAX_NAME_LENGTH, - null=True, - ) - - owner = models.ForeignKey( - User, - related_name="previously_owned_personas", - null=True, - ) - - category = models.ForeignKey( - Category, - related_name="revisions", - null=True, - ) - - description = models.TextField( - null=True, - ) - - url = models.URLField( - null=True, - ) - - text_color = models.CharField( - max_length=MAX_COLOR_LENGTH, - null=True, - ) - - accent_color = models.CharField( - max_length=MAX_COLOR_LENGTH, - null=True, - ) - - status = models.CharField( - max_length=Persona.MAX_STATUS_LENGTH, - null=True, - ) - - def __str__(self): - return "%s - r%s" % (self.revision_of.name, self.revision) - - def resolve(self): - """ - Fills-in (resolves) all the fields of the revision by - computing reverse deltas to future/present revisions. - - >>> p = Persona(name='Test Persona', - ... description='Thos is a test.', - ... url='http://www.blarg.com', - ... category=Category.objects.get(name='Other')) - >>> p.save() - >>> p.description = 'This is a test.' - >>> p.save() - >>> p.name = 'Blarg' - >>> p.save() - >>> p.description = "This is a great test." - >>> p.save() - >>> p.url = "http://www.test.com" - >>> p.save() - >>> r = p.revisions.get(revision=0) - >>> r.resolve() - >>> r.name - u'Test Persona' - >>> r.description - u'Thos is a test.' - >>> r.url - u'http://www.blarg.com' - """ - - persona = self.revision_of - futureRevs = persona.revisions.filter(revision__gt=self.revision) - attrsLeft = [ attr for attr in Persona.VERSIONED_PROPERTIES - if getattr(self, attr) == None ] - for rev in futureRevs: - attrsFound = [] - for attr in attrsLeft: - if getattr(rev, "has_%s" % attr): - setattr(self, attr, getattr(rev, attr)) - attrsFound.append(attr) - if attrsFound: - attrsLeft = [ attr for attr in attrsLeft - if attr not in attrsFound ] - if not attrsLeft: - break - for attr in attrsLeft: - setattr(self, attr, getattr(persona, attr)) - - def save(self): - """ - The save method for a Revision can only be called once, - because Revision objects are meant to be immutable: - - >>> p = Persona(name='Test Persona', - ... url='http://www.blah.com', - ... category=Category.objects.get(name='Other')) - >>> p.save() - >>> p.description = 'This is a test.' - >>> p.save() - >>> r = p.revisions.get(revision=0) - >>> r.status = "deleted" - >>> r.save() - Traceback (most recent call last): - ... - AssertionError: Revisions are immutable - """ - - if self.id == None: - super(Revision, self).save() - else: - raise AssertionError("Revisions are immutable")
--- a/PersonasBackendTemp/personas/sections.py Wed Apr 02 11:59:36 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -from django.core import urlresolvers -from django.contrib.sites.models import Site - -class Sections( object ): - def __init__( self, *sections ): - self.sections = sections - self.sidebar_entries = [] - self.views = {} - self.names = {} - for section in self.sections: - if section.in_sidebar: - self.sidebar_entries.append( section ) - assert section.name not in self.names - self.names[section.name] = section - assert section.view not in self.views - self.views[section.view] = section - - curr_section = section - while curr_section.parent_name: - curr_parent = self.names[curr_section.parent_name] - section.parents.append( curr_parent ) - curr_section = curr_parent - -class Section( object ): - def __init__( self, name, view, in_sidebar = False, - parent_name = None ): - self.name = name - self.view = view - self.in_sidebar = in_sidebar - self.parent_name = parent_name - - # This will be filled out by the parent Sections object. - self.parents = [] - - def url( self ): - return urlresolvers.reverse( self.view ) - -sections = Sections( - Section( "Home", - "PersonasBackend.personas.views.home_view", - in_sidebar = True ), - Section( "Browse", - "PersonasBackend.personas.views.list_view", - parent_name = "Home", - in_sidebar = True ), - Section( "Create", - "PersonasBackend.personas.views.new_view", - parent_name = "Home", - in_sidebar = True ), - Section( "Edit", - "PersonasBackend.personas.views.edit_view", - parent_name = "Home" ), - Section( "Log in", - "django.contrib.auth.views.login", - parent_name = "Home" ), - Section( "Log out", - "django.contrib.auth.views.logout", - parent_name = "Home" ) - ) - -def context( request ): - viewfunc, args, kwargs = urlresolvers.resolve( request.path ) - viewname = ".".join( [viewfunc.__module__, - viewfunc.__name__] ) - return { - "site_name" : Site.objects.get_current().name, - "sidebar_entries" : sections.sidebar_entries, - "section" : sections.views.get( viewname, None ) - }
--- a/PersonasBackendTemp/personas/templates/personas/base.html Wed Apr 02 11:59:36 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <meta http-equiv="Content-Type" - content="text/html; charset=iso-8859-1" /> - <title>{{ section.name }} :: {{ site_name }}</title> - <link rel="stylesheet" - type="text/css" - href="{{ MEDIA_URL }}css/otherpages.css" /> - <link rel="shortcut icon" href="{{ MEDIA_URL }}img/favicon.ico" - type="image/x-icon" /> - </head> -<body> - <div id="content"> - <div id="top"> - - <img src="http://labs.mozilla.com/projects/personas/images/personas-logo-beta.png" - alt="Personas for Firefox" /> - </div> - - <div id="bottom"> - <div><img src="http://labs.mozilla.com/projects/personas/images/otherpages-table-top.png" alt="" /></div> - - <div class="table_middle"> - <div id="sidebar"> - <div class="menu-box"> - <ul> - {% for entry in sidebar_entries %} - {% ifequal entry.name section.name %} - <li class="selected"> - <a href="{{ entry.url }}">{{entry.name}}</a> - </li> - {% else %} - <li><a href="{{ entry.url }}">{{ entry.name }}</a></li> - {% endifequal %} - {% endfor %} - {% if perms.personas.can_publish %} - <li><a href="{% url django.contrib.admin.views.main.index %}" - >Administer</a></li> - {% endif %} - </ul> - </div> - {% if user.is_authenticated %} - <p>Logged in as {{ user.email }}.</p> - <p><a href="{% url logout %}">Log out</a></p> - {% else %} - <a href="https://services.mozilla.com/" >Register</a> | - <a href="{% url login %}">Log in</a> - {% endif %} - </div> - - <div id="section-content"> - <div class="title">{% block title %}{{ section.name }}{% endblock %}</div> - <div class="divider"></div> - - <div class="details"> - {% if messages %} - {% for message in messages %} - <div class="message">{{ message }}</div> - {% endfor %} - {% endif %} - {% block content %}{% endblock %} - </div> - </div> - - <div><img src="http://labs.mozilla.com/projects/personas/images/otherpages-table-foot.png" alt="" /></div> - - </div> - - <div id="footer"> - <div class="labs"> - <a href="http://labs.mozilla.com"><img src="http://labs.mozilla.com/projects/personas/images/mozilla-labs-large.png" alt="Mozilla Labs" border="0" /></a> - - Personas for Firefox is a <a href="http://labs.mozilla.com">Mozilla Labs Project</a>. - </div> - <div class="legal"> - © 2007 Mozilla - <span> - <a href="http://www.mozilla.com/en-US/about/legal.html">Legal Notices</a> | - <a href="http://www.mozilla.com/en-US/privacy-policy.html">Privacy Policy</a> - </span> - </div> - </div> - </div> - </div> -</body> -</html>
--- a/PersonasBackendTemp/personas/templates/personas/edit.html Wed Apr 02 11:59:36 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -{% extends "personas/base.html" %} - -{% block content %} -<form enctype="multipart/form-data" method="post" action="."> - <table class="persona-form corner-box"> - {{ form }} - </table> - <input type="submit" class="amo-submit" value="Submit"/> -</form> -{% endblock %}
--- a/PersonasBackendTemp/personas/templates/personas/home.html Wed Apr 02 11:59:36 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -{% extends "personas/base.html" %} - -{% block title %}What are Personas?{% endblock %} - -{% block content %} -<p>Personas for Firefox is an extension that adds lightweight theming to your browser.</p> -<p>Personas is a prototype that builds upon the ideas that:</p> -<ul> -<li>themes today are too hard to find, install and use</li> -<li>graphic designers should be able to style the browser without having to code</li> -<li>browsers can be more than just desktop software, they can include online components</li> -<li>people just want their computer to be a little more fun and personal</li> -</ul> -{% endblock %}
--- a/PersonasBackendTemp/personas/templates/personas/legacy_persona.xul Wed Apr 02 11:59:36 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" - flex="1" - style="background-repeat: no-repeat;" - onload="document.documentElement.style.backgroundImage = 'url({{image}})'"> - - <!-- Because CSS image loads don't block the load/pageshow events in Firefox 2, - - we load the image in an image tag, which does block those events, and then - - set the background-image property once the image has finished loading. --> - <image id="image" collapsed="true"/> - - <script type="application/javascript;version=1.7"> - <![CDATA[ - document.getElementById("image").setAttribute("src", "{{image}}"); - document.documentElement.style.backgroundPosition = "{{position}}"; - ]]> - </script> -</window>
--- a/PersonasBackendTemp/personas/templates/personas/list.html Wed Apr 02 11:59:36 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -{% extends "personas/base.html" %} - -{% block content %} -{% if personas %} -<p>Here's a list of all available Personas.</p> -<p>If you have the Personas extension installed, just mouseover the -preview image for a Persona to preview it—when your mouse moves -away from the image, your original Persona will replace the preview.</p> -<p>If you like the Persona, you can click on the preview image to set it -as your current Persona.</p> -<p>Enjoy!</p> -<script> -function dispatchPersonaEvent(aType, aNode, aUrl) { - if (aUrl) { - /* TODO: We should only do this if the Persona is successfully - set, i.e. if the user actually has Personas installed, etc. */ - /* TODO: We should probably just use a library like jQuery to - do this for us. */ - var request = new XMLHttpRequest(); - /* TODO: Be reasonable and make this a POST, as this 'ping' will - change the server's state. */ - request.open( "GET", aUrl, true ); - request.onreadystatechange = function() {} - request.send(null); - } - - var event = document.createEvent("Events"); - event.initEvent(aType, true, false); - aNode.dispatchEvent(event); -} -</script> -{% for persona in personas %} -<div class="corner-box"> - <div onclick="dispatchPersonaEvent('SelectPersona', - event.originalTarget, - '{% url report-selection persona.id %}')" - onmouseover="dispatchPersonaEvent('PreviewPersona', - event.originalTarget)" - onmouseout="dispatchPersonaEvent('ResetPersona', - event.originalTarget)"> - <img persona="{{ persona.json_id }}" - category="{{ persona.category.json_id }}" - src="{{ persona.get_header_url }}" class="preview-image" - width="300" height="20" alt="" /> - </div> - <div class="persona-title"> - <h2 class="persona-name">{{ persona.name }}</h2> - {% if persona.owner %} - <span class="developer"> by {{ persona.owner.first_name }} - {{ persona.owner.last_name }}</span> - {% endif %} - </div> - <div class="persona-desc">{{ persona.description|safe }}</div> - {% if perms.personas.can_publish %} - <a href="{% url django.contrib.admin.views.main.change_stage "personas","persona",persona.id %}">Edit</a> - {% else %} - {% ifequal persona.owner user %} - <a href="{% url edit-persona persona.id %}">Edit</a> - {% endifequal %} - {% endif %} -</div> -{% endfor %} -{% else %} -<p>There are currently no personas available.</p> -{% endif %} -{% endblock %}
--- a/PersonasBackendTemp/personas/templates/personas/logged_out.html Wed Apr 02 11:59:36 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -{% extends "personas/base.html" %} - -{% block content %} -<p>{{ title }}</p> -{% endblock %}
--- a/PersonasBackendTemp/personas/templates/personas/login.html Wed Apr 02 11:59:36 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -{% extends "personas/base.html" %} - -{% block content %} -{% if form.has_errors %} -<p>Your username and password didn't match. Please try again.</p> -{% endif %} -<form method="post" action="." class="persona-form corner-box"> - <table> - <tr> - <td><label for="id_username">Username:</label></td> - <td>{{ form.username }}</td> - </tr> - <tr> - <td><label for="id_password">Password:</label></td> - <td>{{ form.password }}</td> - </tr> - </table> - <input type="submit" class="amo-submit" value="Log in" /> - <input type="hidden" name="next" value="{{ next }}" /> -</form> -{% endblock %}
--- a/PersonasBackendTemp/personas/templates/personas/todo.html Wed Apr 02 11:59:36 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -{% extends "personas/base.html" %} - -{% block content %} -This page is under construction. -{% endblock %}
--- a/PersonasBackendTemp/personas/tests.py Wed Apr 02 11:59:36 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -import unittest -import datetime - -from django.test.client import Client -from django.core.urlresolvers import reverse -from PersonasBackend.personas import models - -class JsonTests( unittest.TestCase ): - def setUp( self ): - for persona in models.Persona.objects.all(): - persona.delete() - self.cat = models.Category( name = "Random Things" ) - self.cat.save() - self.persona = models.Persona( - name = "Test Persona", - category = self.cat, - url = "http://www.blarg.com/mypersona", - status = "published" - ) - self.persona.save() - - def tearDown( self ): - self.persona.delete() - self.cat.delete() - - def testCategoriesWorks( self ): - # Just a smoke test to make sure nothing crashes... - client = Client() - response = client.get( reverse("personas-categories-json") ) - assert response.status_code == 200 - - def testAllPersonasWorks( self ): - # Just a smoke test to make sure nothing crashes... - client = Client() - response = client.get( reverse("personas-all-json") ) - assert response.status_code == 200 - - def testPublishDateIsUpdatedProperly( self ): - p = models.Persona( - name='Yet Another Test Persona', - url='http://www.test.com/testpersona', - category=models.Category.objects.get(name='Other')) - - p.save() - self.assertEquals( p.status, "unpublished" ) - self.assertEquals( p.date_published, None ) - - p.status = "published" - now = datetime.datetime.now() - p.save() - assert p.date_published >= now - -if __name__ == "__main__": - unittest.main()
--- a/PersonasBackendTemp/personas/urls.py Wed Apr 02 11:59:36 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -from django.conf.urls.defaults import * - -urlpatterns = patterns('', - # JSON feeds - - # TODO: Replace the '.+' at the beginning of these with - # a real regexp that conveys the locale to the view. - url(r'^.+/personas_categories.dat$', - 'PersonasBackend.personas.json_feeds.categories', - name='personas-categories-json'), - url(r'^.+/personas_all.dat$', - 'PersonasBackend.personas.json_feeds.personas', - name='personas-all-json'), - - # Dynamic wrappers for views - url(r'^legacy/(?P<name>.+)$', - 'PersonasBackend.personas.views.legacy_cbeard_persona', - name='legacy-cbeard-persona'), - - # Auth - url(r'^login/$', 'django.contrib.auth.views.login', - {'template_name':'personas/login.html'}, - name='login'), - url(r'^logout/$', 'django.contrib.auth.views.logout', - {'template_name':'personas/logged_out.html'}, - name='logout'), - - # AJAX calls - url(r'^ajax/report_selection/(?P<persona_id>\d+)/$', - 'PersonasBackend.personas.ajax.report_selection', - name='report-selection'), - - # Personas UI - url(r'^new/$', - 'PersonasBackend.personas.views.new_view', - name='new-persona'), - url(r'^(?P<persona_id>\d+)/edit/$', - 'PersonasBackend.personas.views.edit_view', - name='edit-persona'), - url(r'^list/$', 'PersonasBackend.personas.views.list_view', - name='list-personas'), - url(r'^$', 'PersonasBackend.personas.views.home_view', - name='personas-home'), - - # 'Fake' scaffolding view for pages that still need to be - # constructed. - url(r'^TODO/$', 'PersonasBackend.personas.views.todo_view', - name='TODO'), -)
--- a/PersonasBackendTemp/personas/views.py Wed Apr 02 11:59:36 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -from django.http import HttpResponseRedirect, HttpResponseForbidden -from django.http import HttpResponse, HttpResponseBadRequest -from django.template import RequestContext -from django.contrib.auth.decorators import login_required -from django.core.urlresolvers import reverse -from django.shortcuts import render_to_response, get_object_or_404 - -from PersonasBackend.personas import models -from PersonasBackend.personas import forms - -def legacy_cbeard_persona( request, name ): - PREFIX = "http://sm-labs01.mozilla.org/legacy-personas/" - FOOTER_URL = "%(prefix)s%(name)s/stbar-%(name)s.jpg" - HEADER_URL = "%(prefix)s%(name)s/tbox-%(name)s.jpg" - - urldict = {"prefix" : PREFIX, "name" : name} - - action = request.GET.get( "action", "" ) - - if action == "footer": - position = "bottom left" - img_src = FOOTER_URL % urldict - elif action == "header": - position = "top right" - img_src = HEADER_URL % urldict - else: - return HttpResponseBadRequest( "Invalid or unsupported action: %s" % - action ) - - return render_to_response( - "personas/legacy_persona.xul", - { "image" : img_src, "position" : position }, - mimetype = "application/vnd.mozilla.xul+xml" - ) - -def list_view( request ): - personas = models.Persona.objects.filter( status="published" ) - return render_to_response( - "personas/list.html", - { "personas" : personas, - "title" : "Browse Personas" }, - context_instance = RequestContext(request) - ) - -def home_view( request ): - return render_to_response( - "personas/home.html", - { "title" : "Home" }, - context_instance = RequestContext(request) - ) - -def todo_view( request ): - return render_to_response( - "personas/todo.html", - { "title" : "Under Construction" }, - context_instance = RequestContext(request) - ) - -def new_view( request ): - return edit_view( request ) - -@login_required -def edit_view( request, persona_id=None ): - if persona_id is None: - persona = None - pageTitle = "Create a new Persona" - else: - persona = get_object_or_404( models.Persona, id=persona_id ) - if not persona.can_user_edit( request.user ): - return HttpResponseForbidden( - "<h1>You do not have permission to edit " - "this Persona.</h1>" - ) - pageTitle = "Edit Persona" - - if request.method == "POST": - form = forms.PersonaForm( request.POST, - instance=persona ) - if form.is_valid(): - newPersona = form.save( commit=False ) - newPersona.save( updater = request.user ) - if persona is None: - msgText = ("Persona created successfully. It will need " - "to be reviewed by a staff member " - "before it is published.") - else: - msgText = ("Persona edited successfully. Your changes " - "will need to be approved by a staff member " - "before they can take effect.") - request.user.message_set.create( message = msgText ) - url = reverse("edit-persona", args=[newPersona.id]) - return HttpResponseRedirect( url ) - else: - form = forms.PersonaForm( instance=persona ) - - return render_to_response( - "personas/edit.html", - { "form" : form, - "title" : pageTitle }, - context_instance = RequestContext(request) - )
--- a/PersonasBackendTemp/settings.py Wed Apr 02 11:59:36 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,109 +0,0 @@ -# Django settings for PersonasBackend project. - -import os - -myPath = os.path.abspath( os.path.dirname( __file__ ) ) - -DEBUG = True -TEMPLATE_DEBUG = DEBUG - -ADMINS = ( - # ('Your Name', 'your_email@domain.com'), -) - -MANAGERS = ADMINS - -DATABASE_ENGINE = 'sqlite3' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'ado_mssql'. -DATABASE_NAME = os.path.join( myPath, "temp_db" ) # Or path to database file if using sqlite3. -DATABASE_USER = '' # Not used with sqlite3. -DATABASE_PASSWORD = '' # Not used with sqlite3. -DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3. -DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3. - -# Local time zone for this installation. Choices can be found here: -# http://www.postgresql.org/docs/8.1/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE -# although not all variations may be possible on all operating systems. -# If running in a Windows environment this must be set to the same as your -# system time zone. -TIME_ZONE = 'America/Chicago' - -# Language code for this installation. All choices can be found here: -# http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes -# http://blogs.law.harvard.edu/tech/stories/storyReader$15 -LANGUAGE_CODE = 'en-us' - -SITE_ID = 1 - -# If you set this to False, Django will make some optimizations so as not -# to load the internationalization machinery. -USE_I18N = True - -# Absolute path to the directory that holds media. -# Example: "/home/media/media.lawrence.com/" -MEDIA_ROOT = os.path.normpath( os.path.join( myPath, "..", "media" ) ) - -BASE_DIR = "personas/" - -# URL that handles the media served from MEDIA_ROOT. -# Example: "http://media.lawrence.com" -MEDIA_URL = '/%smedia/' % BASE_DIR - -# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a -# trailing slash. -# Examples: "http://foo.com/media/", "/media/". -ADMIN_MEDIA_PREFIX = '/%sadmin/media/' % BASE_DIR - -# Make this unique, and don't share it with anybody. -SECRET_KEY = 'x=0z4lnv#vws4p4a%r(fb=(wh&o4k)k!5!a9b*3-j7s87^v43d' - -# List of callables that know how to import templates from various sources. -TEMPLATE_LOADERS = ( - 'django.template.loaders.filesystem.load_template_source', - 'django.template.loaders.app_directories.load_template_source', -# 'django.template.loaders.eggs.load_template_source', -) - -MIDDLEWARE_CLASSES = ( - 'django.middleware.cache.CacheMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.middleware.doc.XViewMiddleware', -) - -LOGIN_URL = '/%slogin/' % BASE_DIR -LOGIN_REDIRECT_URL = '/%s' % BASE_DIR - -ROOT_URLCONF = 'PersonasBackend.urls' - -TEMPLATE_DIRS = ( - # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". - # Always use forward slashes, even on Windows. - # Don't forget to use absolute paths, not relative paths. - os.path.normpath( os.path.join( myPath, "..", "templates" ) ), -) - -INSTALLED_APPS = ( - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.sites', - 'django.contrib.admin', - 'PersonasBackend.personas', -) - -TEMPLATE_CONTEXT_PROCESSORS = ( - "django.core.context_processors.auth", - "django.core.context_processors.debug", - "django.core.context_processors.i18n", - "django.core.context_processors.media", - "PersonasBackend.personas.sections.context", -) - -CACHE_BACKEND = 'locmem:///' -CACHE_MIDDLEWARE_SECONDS = 5 -CACHE_MIDDLEWARE_KEY_PREFIX = "personas" - -AUTHENTICATION_BACKENDS = ( - "PersonasBackend.weaveproxyauth.Backend", -)
--- a/PersonasBackendTemp/urls.py Wed Apr 02 11:59:36 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -import os - -from django.conf.urls.defaults import * -from PersonasBackend import settings -import django.contrib.admin - -urlpatterns = patterns('', - # Admin media - # TODO: Remove the static.serve, b/c it's supposedly insecure. - (r'^%sadmin/media/(?P<path>.*)$' % settings.BASE_DIR, - 'django.views.static.serve', - {'document_root': os.path.join( django.contrib.admin.__path__[0], - "media" )}), - - # Admin - (r'^%sadmin/' % settings.BASE_DIR, - include('django.contrib.admin.urls')), - - # Personas media - # TODO: Remove the static.serve, b/c it's supposedly insecure. - (r'^%smedia/(?P<path>.*)$' % settings.BASE_DIR, - 'django.views.static.serve', - {'document_root': settings.MEDIA_ROOT}), - - # Personas - (r'^%s' % settings.BASE_DIR, - include('PersonasBackend.personas.urls')), -)
--- a/PersonasBackendTemp/utils.py Wed Apr 02 11:59:36 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -from django.contrib.sites.models import Site - -def make_absolute_url( path ): - domain = Site.objects.get_current().domain - if domain == "localhost": - domain = "localhost:8000" - url = "http://%s%s" % (domain, path) - return url
--- a/PersonasBackendTemp/weaveproxyauth.py Wed Apr 02 11:59:36 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -import sha -import urllib2 -import httplib - -from django.contrib.auth.models import User - -class Backend(object): - def authenticate(self, username=None, password=None): - hexuser = sha.sha(username).hexdigest() - url = "https://services.mozilla.com/user/%s/" % hexuser - authHandler = urllib2.HTTPBasicAuthHandler() - authHandler.add_password("services.mozilla.com - proxy", - "services.mozilla.com", - username, - password) - - opener = urllib2.build_opener(authHandler) - - try: - obj = opener.open(url) - obj.read() - auth_successful = True - except urllib2.HTTPError, e: - if e.code == httplib.UNAUTHORIZED: - auth_successful = False - else: - raise - - if auth_successful: - try: - user = User.objects.get(email=username) - except User.DoesNotExist: - # We have to go through this annoyance because Django - # auth requires us to enter a username, and the username - # can be no more than 30 characters and can't include - # anything other than alphanumeric characters. - munged_username = "".join( - [char for char in username if char.isalnum()] - )[:25] - - offset = 0 - while User.objects.filter( - username = munged_username + str(offset) - ): - offset += 1 - - user = User(username=munged_username + str(offset), - password="Retrieved from Weave", - email=username) - user.save() - return user - - return None - - def get_user(self, user_id): - try: - return User.objects.get(pk=user_id) - except User.DoesNotExist: - return None
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/personasbackend/manage.py Wed Apr 02 11:59:58 2008 -0700 @@ -0,0 +1,11 @@ +#!/usr/bin/env python +from django.core.management import execute_manager +try: + import settings # Assumed to be in the same directory. +except ImportError: + import sys + sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__) + sys.exit(1) + +if __name__ == "__main__": + execute_manager(settings)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/personasbackend/personas/ajax.py Wed Apr 02 11:59:58 2008 -0700 @@ -0,0 +1,10 @@ +from django.http import HttpResponse +from django.shortcuts import get_object_or_404 + +from PersonasBackend.personas import models + +def report_selection( request, persona_id ): + persona = get_object_or_404( models.Persona, id=persona_id ) + persona.popularity += 1 + persona.save() + return HttpResponse()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/personasbackend/personas/fixtures/initial_data.xml Wed Apr 02 11:59:58 2008 -0700 @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8"?> +<django-objects version="1.0"><object pk="1" model="personas.category"><field type="CharField" name="name">Other</field></object><object pk="2" model="personas.category"><field type="CharField" name="name">Geometric</field></object><object pk="3" model="personas.category"><field type="CharField" name="name">Sports</field></object><object pk="4" model="personas.category"><field type="CharField" name="name">Scenery</field></object><object pk="5" model="personas.category"><field type="CharField" name="name">Nature</field></object><object pk="6" model="personas.category"><field type="CharField" name="name">Holidays</field></object><object pk="7" model="personas.category"><field type="CharField" name="name">Foxkeh</field></object><object pk="8" model="personas.category"><field type="CharField" name="name">Firefox</field></object><object pk="1" model="personas.persona"><field type="CharField" name="name">Firefox Logo</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">8</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=firefox_b</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="2" model="personas.persona"><field type="CharField" name="name">Firefox Flicks</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">8</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=firefox_flicks</field><field type="CharField" name="text_color">#FFFFFF</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="3" model="personas.persona"><field type="CharField" name="name">Mozilla Classic</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">8</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=mozilla_classic</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="4" model="personas.persona"><field type="CharField" name="name">Foxkeh Straw</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">7</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=foxkeh_straw</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="5" model="personas.persona"><field type="CharField" name="name">Foxkeh Hanami</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">7</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=foxkeh_hanami</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="6" model="personas.persona"><field type="CharField" name="name">Foxkeh Hinimatsuri</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">7</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=foxkeh_hinimatsuri</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="7" model="personas.persona"><field type="CharField" name="name">Foxkeh Kodomo No Hi</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">7</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=foxkeh_kodomo_no_hi</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="8" model="personas.persona"><field type="CharField" name="name">Foxkeh Setsubun</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">7</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=foxkeh_setsubun</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="9" model="personas.persona"><field type="CharField" name="name">Foxkeh Giant Butterbur</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">7</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=foxkeh_butterbur</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="10" model="personas.persona"><field type="CharField" name="name">Foxkeh Tanabata</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">7</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=foxkeh_tanabata</field><field type="CharField" name="text_color">#FFFFFF</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="11" model="personas.persona"><field type="CharField" name="name">Viva Firefox</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">8</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=viva</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="12" model="personas.persona"><field type="CharField" name="name">Developer Kit</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">8</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=kit</field><field type="CharField" name="text_color">#FFFFFF</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="13" model="personas.persona"><field type="CharField" name="name">Tranquility</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">5</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=tranquility</field><field type="CharField" name="text_color">#FFFFFF</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="14" model="personas.persona"><field type="CharField" name="name">California Sunset</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">4</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=california_sunset</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="15" model="personas.persona"><field type="CharField" name="name">Wood Paneling</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">1</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=wood_paneling</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="16" model="personas.persona"><field type="CharField" name="name">Hearts</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">1</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=hearts</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="17" model="personas.persona"><field type="CharField" name="name">Blue Spheres</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">1</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=blue_spheres</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="18" model="personas.persona"><field type="CharField" name="name">Les Diablerets</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">4</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=les_diablerets</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="19" model="personas.persona"><field type="CharField" name="name">Seagull</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">4</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=seagull</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="20" model="personas.persona"><field type="CharField" name="name">Verdelet</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">4</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=verdelet</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="21" model="personas.persona"><field type="CharField" name="name">Green Wave</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">1</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=green_wave</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="22" model="personas.persona"><field type="CharField" name="name">Golf</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">3</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=golf</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="23" model="personas.persona"><field type="CharField" name="name">Basketball</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">3</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=bball</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="24" model="personas.persona"><field type="CharField" name="name">Antique Wallpaper</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">1</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=antique_wallpaper</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="25" model="personas.persona"><field type="CharField" name="name">Bamboo</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">5</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=bamboo</field><field type="CharField" name="text_color">#FFFFFF</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="26" model="personas.persona"><field type="CharField" name="name">Plaid</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">2</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=plaid</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="27" model="personas.persona"><field type="CharField" name="name">Soccer</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">3</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=soccer</field><field type="CharField" name="text_color">#FFFFFF</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="28" model="personas.persona"><field type="CharField" name="name">Suede</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">1</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=suede</field><field type="CharField" name="text_color">#FFFFFF</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="29" model="personas.persona"><field type="CharField" name="name">Aquarium</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">5</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=aquarium</field><field type="CharField" name="text_color">#FFFFFF</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="30" model="personas.persona"><field type="CharField" name="name">Dialogonal Lines</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">2</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=diagonal_lines</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="31" model="personas.persona"><field type="CharField" name="name">Dots</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">2</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=dots</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="32" model="personas.persona"><field type="CharField" name="name">Golden Gate Bridge</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">4</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=golden_gate_bridge</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="33" model="personas.persona"><field type="CharField" name="name">Grass</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">5</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=grass</field><field type="CharField" name="text_color">#FFFFFF</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="34" model="personas.persona"><field type="CharField" name="name">Foxkeh Green Winter</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">7</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=foxkeh_green_winter</field><field type="CharField" name="text_color">#FFFFFF</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="35" model="personas.persona"><field type="CharField" name="name">Jellyfish</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">5</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=jellyfish</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="36" model="personas.persona"><field type="CharField" name="name">Yosemite</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">4</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=yosemite</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="37" model="personas.persona"><field type="CharField" name="name">Snowman</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">6</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=snowman</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="38" model="personas.persona"><field type="CharField" name="name">Snowflakes</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">6</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=snowflakes</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="39" model="personas.persona"><field type="CharField" name="name">Reindeer</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">6</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=reindeer</field><field type="CharField" name="text_color">#FFFFFF</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="40" model="personas.persona"><field type="CharField" name="name">Foxkeh Canoe</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">7</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=foxkeh_canoe</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="41" model="personas.persona"><field type="CharField" name="name">Foxkeh Helloween</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">7</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=foxkeh_helloween</field><field type="CharField" name="text_color">#FFFFFF</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="42" model="personas.persona"><field type="CharField" name="name">Foxkeh Susuki</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">7</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=foxkeh_susuki</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="43" model="personas.persona"><field type="CharField" name="name">Foxkeh Hanabi</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">7</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=foxkeh_hanabi</field><field type="CharField" name="text_color">#FFFFFF</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="44" model="personas.persona"><field type="CharField" name="name">Paper</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">1</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=paper</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="45" model="personas.persona"><field type="CharField" name="name">Winter</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">6</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=winter</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="46" model="personas.persona"><field type="CharField" name="name">Leather</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">1</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=leather</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="47" model="personas.persona"><field type="CharField" name="name">Niagra Falls</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">4</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=niagra_falls</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="48" model="personas.persona"><field type="CharField" name="name">Groovy Blue</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">1</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=groovy_blue</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="49" model="personas.persona"><field type="CharField" name="name">Groovy Hearts</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">1</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=groovy_hearts</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="50" model="personas.persona"><field type="CharField" name="name">Groovy Orange</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">1</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=groovy_orange</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object><object pk="51" model="personas.persona"><field type="CharField" name="name">Groovy Pink</field><field to="auth.user" name="owner" rel="ManyToOneRel"><None></None></field><field to="personas.category" name="category" rel="ManyToOneRel">1</field><field type="TextField" name="description">&nbsp;</field><field type="CharField" name="url">http://personas-view/legacy-cbeard-persona?name=groovy_pink</field><field type="CharField" name="text_color">#000000</field><field type="CharField" name="accent_color"></field><field type="DateTimeField" name="date_published">2008-03-28 16:49:23</field><field type="DateTimeField" name="date_updated">2008-03-28 16:49:23</field><field to="auth.user" name="updater" rel="ManyToOneRel"><None></None></field><field type="PositiveIntegerField" name="revision">0</field><field type="PositiveIntegerField" name="popularity">0</field><field type="CharField" name="status">published</field></object></django-objects>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/personasbackend/personas/forms.py Wed Apr 02 11:59:58 2008 -0700 @@ -0,0 +1,47 @@ +import django.newforms as forms +from PersonasBackend.personas import models + +class PersonaForm( forms.ModelForm ): + """ + Form given to normal users who don't have the permission to + publish Personas. + """ + + class Meta: + model = models.Persona + exclude = ["owner", "date_published", "popularity", "status"] + + agree_to_terms = forms.BooleanField( + label = "I agree to the terms of use.", + # TODO: setting required to True doesn't seem to have any effect, + # but the Django docs say it should ensure that the checkbox + # is filled out. + required = True, + help_text = ("Terms of use: I agree that Mozilla is providing " + "a service by hosting the " + "content I am submitting, and that they are in no " + "way responsible for any damages that occur as " + "a result of hosting said content.") + ) + + def _color_cleaner( self, field ): + models.ensure_color_is_valid( + self.cleaned_data[field], + error_class = forms.ValidationError + ) + return self.cleaned_data[field] + + def clean_text_color( self ): + return self._color_cleaner( "text_color" ) + + def clean_accent_color( self ): + return self._color_cleaner( "accent_color" ) + + def clean( self ): + if not self.cleaned_data["agree_to_terms"]: + raise forms.ValidationError( + "You must agree to the terms of service to " + "submit your Persona." + ) + + return self.cleaned_data
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/personasbackend/personas/json_feeds.py Wed Apr 02 11:59:58 2008 -0700 @@ -0,0 +1,68 @@ +from django.http import HttpResponse +from django.utils import simplejson + +from PersonasBackend.personas import models + +NEW_MENU_ID = "personas-new-menu" +POPULAR_MENU_ID = "personas-popular-menu" + +def _makeJsonResponse( obj ): + json = simplejson.dumps( obj, indent=4 ) + response = HttpResponse( json ) + response["Content-Type"] = "text/plain" + return response + +def categories( request ): + categoryDicts = [ + {"label": "Most Popular", "id" : POPULAR_MENU_ID, + "type" : "list", "parent" : "top" }, + {"label": "Recent", "id" : "personas-recent-menu", + "type" : "recent", "parent" : "top" }, + {"label": "New", "id" : NEW_MENU_ID, + "type" : "list", "parent" : "top" }, + {"label": "All", "id" : "personas-category-menu", + "type" : "category", "parent" : "top" }, + ] + + for category in models.Category.objects.all(): + categoryDicts.append( + {"label" : category.name, + "id" : category.json_id, + "type" : "list", + "parent" : "personas-category-menu"} + ) + + return _makeJsonResponse( {"categories" : categoryDicts} ) + +def personas( request ): + personaDicts = [] + + isPopular = {} + isNew = {} + + published = models.Persona.objects.filter( status="published" ) + + for persona in published.order_by( "-popularity" )[:10]: + isPopular[persona.id] = True + + for persona in published.order_by( "-date_published" )[:10]: + isNew[persona.id] = True + + for persona in published: + categories = [persona.category.json_id] + if persona.id in isPopular: + categories.append( POPULAR_MENU_ID ) + if persona.id in isNew: + categories.append( NEW_MENU_ID ) + + personaDicts.append( + {"label" : persona.name, + "id" : persona.json_id, + "textColor" : persona.text_color, + "accentColor" : persona.accent_color, + "baseURL" : persona.resolved_url, + "menu" : ",".join( categories ), + "preview" : "yes"} + ) + + return _makeJsonResponse( {"personas" : personaDicts} )
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/personasbackend/personas/models.py Wed Apr 02 11:59:58 2008 -0700 @@ -0,0 +1,604 @@ +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (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.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is PersonasBackend. +# +# The Initial Developer of the Original Code is Mozilla. +# Portions created by the Initial Developer are Copyright (C) 2008 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Atul Varma <atul@mozilla.org> +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +""" +models.py + +This module contains the models for the Personas application. + +Note that changes to Personas are automatically revision-controlled. +Among other things, this allows for: + + (A) A humane user interface that supports undo operations. + + (B) A workflow that allows for Personas to be changed by a submitter + and reviewed while the original, unchanged Persona remains + published and accessible by clients. +""" + +import datetime + +from django.db import models +from django.core.urlresolvers import reverse +from django.contrib.auth.models import User +from django.core.validators import ValidationError + +from PersonasBackend.utils import make_absolute_url + +MAX_COLOR_LENGTH = 7 + +def parse_personas_view_url( url ): + """ + TODO: Document this. + + Examples: + + >>> parse_personas_view_url( "http://personas-view/blargy?thing=blarg" ) + {'kwargs': {'thing': 'blarg'}, 'view': 'blargy'} + + >>> parse_personas_view_url( "http://porsonas-view/blargy?thing=blarg" ) + """ + + if not url.startswith( "http://personas-view/" ): + return None + + import urlparse + import cgi + + _, _, path, _, query, _ = urlparse.urlparse( url ) + view = path[1:] + kwargs = cgi.parse_qs( query ) + + # It is completely ridiculous that we have to do this, but + # apparently we do, because django's reverse() doesn't like being + # passed dictionaries with unicode keys. + string_kwargs = {} + for key in kwargs: + string_kwargs[str(key)] = str(kwargs[key][0]) + + return {'view':view, 'kwargs':string_kwargs} + +def ensure_color_is_valid( color, + error_class = ValidationError ): + """ + Given a color string, raises a ValidationError if the color isn't + formatted properly. + + Examples: + + >>> ensure_color_is_valid('') + + >>> ensure_color_is_valid('blah') + Traceback (most recent call last): + ... + ValidationError: [u"The color must start with a '#'."] + + >>> ensure_color_is_valid('#aaaaaaa') + Traceback (most recent call last): + ... + ValidationError: [u'The color is too long.'] + + >>> ensure_color_is_valid('#aaaaa') + Traceback (most recent call last): + ... + ValidationError: [u'The color is too short.'] + + >>> ensure_color_is_valid('#aaazaa') + Traceback (most recent call last): + ... + ValidationError: [u"The character 'z' isn't valid."] + + >>> ensure_color_is_valid('#aaaaaa') + >>> ensure_color_is_valid('#FFFF11') + """ + + HEX_CHARS = "0123456789abcdef" + + if not color: + return + + if not color.startswith("#"): + raise error_class( "The color must start with a '#'." ) + if len(color) > MAX_COLOR_LENGTH: + raise error_class( "The color is too long." ) + if len(color) < MAX_COLOR_LENGTH: + raise error_class( "The color is too short." ) + for char in color.lower()[1:MAX_COLOR_LENGTH]: + if char not in HEX_CHARS: + raise error_class( "The character '%s' isn't valid." % char ) + +class Category(models.Model): + """ + Represents a Personas category; every Persona can be assigned one, + and only one, category. + """ + + class Admin: + pass + + class Meta: + verbose_name_plural = "categories" + + name = models.CharField( + "Category name", + max_length=50, + unique=True, + ) + + def __str__(self): + return self.name + + def _get_json_id( self ): + return "personas-category-%d" % self.id + + json_id = property( _get_json_id ) + +class Persona(models.Model): + """ + Encapsulates the most recent revision of a Persona. + """ + + class Admin: + list_display = ["name", "date_updated", "status"] + + class Meta: + permissions = ( + ("can_publish", "Can publish"), + ) + + MAX_NAME_LENGTH = 50 + + name = models.CharField( + max_length=MAX_NAME_LENGTH, + blank=False, + ) + + owner = models.ForeignKey( + User, + help_text=("The user who owns this persona can make " + "changes to it."), + related_name="owned_personas", + # TODO: Consider making this null=False. Keeping it true + # makes it easier to write tests, though. + null=True, + blank=True, + ) + + category = models.ForeignKey( + Category, + related_name="personas", + null=False, + ) + + description = models.TextField( + help_text = "HTML is allowed.", + blank=False, + ) + + url = models.URLField( + "Persona URL", + help_text=("URL for the content that will be placed behind " + "the browser's chrome."), + verify_exists=False, + blank=False, + ) + + def __get_resolved_url(self): + viewinfo = parse_personas_view_url( self.url ) + if not viewinfo: + return self.url + else: + return make_absolute_url( reverse( + viewinfo['view'], + kwargs = viewinfo['kwargs'] + ) ) + + resolved_url = property(__get_resolved_url) + + text_color = models.CharField( + help_text=("The RGB color, as a #RRGGBB color hash, " + "of the color of text that will be displayed " + "on the persona."), + max_length=MAX_COLOR_LENGTH, + validator_list=[ensure_color_is_valid], + blank=True + ) + + accent_color = models.CharField( + help_text=("The RGB color, as a #RRGGBB color hash, " + "of the accent colors that will be displayed " + "on the persona."), + max_length=MAX_COLOR_LENGTH, + validator_list=[ensure_color_is_valid], + blank=True, + ) + + date_published = models.DateTimeField( + help_text=("The date that the Persona was last published."), + null=True, + editable=True, + ) + + date_updated = models.DateTimeField( + # This ensures that this field is updated with the current + # timestamp whenever the record is changed. + auto_now=True, + null=False, + editable=False, + ) + + updater = models.ForeignKey( + User, + help_text="The user who made this revision.", + related_name="changed_personas", + null=True, + editable=False + ) + + revision = models.PositiveIntegerField( + "Revision number", + help_text=("This number is incremented whenever the Persona " + "is changed."), + null=False, + editable=False, + ) + + popularity = models.PositiveIntegerField( + "Popularity", + help_text=("A number indicating how popular the Persona is; the " + "higher this value, the better."), + default=0, + null=False, + ) + + MAX_STATUS_LENGTH = 10 + + status = models.CharField( + max_length=MAX_STATUS_LENGTH, + choices=(("published", "Published"), + ("unpublished", "Unpublished"), + ("deleted", "Deleted")), + blank=False, + help_text=("Status of the Persona; can be deleted, published, " + "or unpublished (i.e., pending for review).") + ) + + def __str__(self): + return self.name + + # These are the properties of this record that are "versioned", + # i.e. tracked by built-in revision control when changed. + VERSIONED_PROPERTIES = ( + "name", + "owner", + "category", + "description", + "url", + "text_color", + "accent_color", + "status", + ) + + def __make_new_revision(self): + """ + Detect if any of our versioned properties have changed, and if + so, make a new revision. + """ + + original = Persona.objects.get(id=self.id) + + assert original.revision == self.revision + + delta = {} + for attr in self.VERSIONED_PROPERTIES: + origValue = getattr(original, attr) + newValue = getattr(self, attr) + if origValue != newValue: + delta[attr] = origValue + if delta: + rev = Revision( + revision_of = original, + date_updated = original.date_updated, + updater = original.updater, + revision = original.revision + ) + + for attr in delta: + setattr(rev, attr, delta[attr]) + setattr(rev, "has_%s" % attr, True) + rev.save() + + self.revision += 1 + + def save( self, updater=None ): + """ + Saves the object. If a versioned property is changed, a new + revision is generated automatically. + + Example: + + >>> p = Persona(name='Test Persona', + ... description='Thos is a test.', + ... url='http://blarg.com', + ... category=Category.objects.get(name='Other')) + >>> p.save() + >>> p.revision + 0 + >>> p.revisions.all() + [] + + >>> p.description = 'This is a test.' + >>> p.url = 'http://blarg2.com' + >>> p.save() + >>> p.revision + 1 + >>> p.revisions.all() + [<Revision: Test Persona - r0>] + >>> p.revisions.get(revision=0).description + u'Thos is a test.' + >>> p.revisions.get(revision=0).url + u'http://blarg.com' + """ + + if updater: + self.updater = updater + else: + # We were probably saved through the admin interface, + # which saves its own separate history of changes. + self.updater = None + + if self.id == None: + # We're a brand-new Persona. + self.revision = 0 + if not self.owner: + self.owner = self.updater + assert self.owner == self.updater + if not self.status: + if ( self.updater and + self.updater.has_perm( "personas.can_publish" ) ): + # If the person creating the Persona can publish + # Personas, mark this new Persona as published, by + # default. + self.status = "published" + else: + # Otherwise, mark this new Persona as unpublished by + # default. + self.status = "unpublished" + if self.status == "published": + self.date_published = datetime.datetime.now() + else: + # We're an existing Persona that's being modified. + + if self.updater: + if not self.can_user_edit( self.updater ): + # The user can't actually edit this Persona, reject + # the change. View logic should've prevented this + # from ever being the case, so we're going to be + # ungraceful here. + raise AssertionError( "User can't edit this persona." ) + + if ( self.status == "published" and + not self.updater.has_perm( "personas.can_publish" ) ): + # The Persona is currently published, but a user + # without publishing permissions has just changed it, + # so mark it as unpublished so an editor can review it + # before re-publishing it. + + self.status = "unpublished" + + original = Persona.objects.get(id=self.id) + + if ( (original.status != self.status) and + (self.status == "published") ): + self.date_published = datetime.datetime.now() + + self.__make_new_revision() + + super(Persona, self).save() + + def can_user_edit( self, user ): + """ + Returns whether the given User can edit this Persona. + """ + + return ( user.has_perm( "personas.can_publish" ) or + self.owner == user ) + + def _get_json_id( self ): + return "persona-%d" % self.id + + json_id = property( _get_json_id ) + +class Revision(models.Model): + """ + Represents an old revision of a Persona. + + This record only stores a "reverse delta" relative to the revision + that follows it; for instance, if a user changes a Persona at + revision 0 by modifying its description, then the Revision record + for revision 0 will contain only the description for the Persona + at that revision, since all other properties can be obtained by + looking at revision 1. In this way, the complete "picture" of + revision 0 can be reconstructed by starting at the record for + revision 0 and traveling to newer revisions until every field of + the Persona has been populated. + """ + + class Meta: + unique_together = (("revision_of", "revision"),) + ordering = ["revision"] + + # Auto-generated fields + + revision_of = models.ForeignKey( + Persona, + verbose_name="The Persona that this record is an old revision of", + related_name="revisions", + null=False, + ) + + date_updated = models.DateTimeField( + null=False, + ) + + updater = models.ForeignKey( + User, + related_name="previously_changed_revisions", + null=True, + ) + + revision = models.PositiveIntegerField( + null=False, + ) + + # Versioned fields + + for attr in Persona.VERSIONED_PROPERTIES: + locals()["has_%s" % attr] = models.BooleanField(default=False) + del attr + + name = models.CharField( + max_length=Persona.MAX_NAME_LENGTH, + null=True, + ) + + owner = models.ForeignKey( + User, + related_name="previously_owned_personas", + null=True, + ) + + category = models.ForeignKey( + Category, + related_name="revisions", + null=True, + ) + + description = models.TextField( + null=True, + ) + + url = models.URLField( + null=True, + ) + + text_color = models.CharField( + max_length=MAX_COLOR_LENGTH, + null=True, + ) + + accent_color = models.CharField( + max_length=MAX_COLOR_LENGTH, + null=True, + ) + + status = models.CharField( + max_length=Persona.MAX_STATUS_LENGTH, + null=True, + ) + + def __str__(self): + return "%s - r%s" % (self.revision_of.name, self.revision) + + def resolve(self): + """ + Fills-in (resolves) all the fields of the revision by + computing reverse deltas to future/present revisions. + + >>> p = Persona(name='Test Persona', + ... description='Thos is a test.', + ... url='http://www.blarg.com', + ... category=Category.objects.get(name='Other')) + >>> p.save() + >>> p.description = 'This is a test.' + >>> p.save() + >>> p.name = 'Blarg' + >>> p.save() + >>> p.description = "This is a great test." + >>> p.save() + >>> p.url = "http://www.test.com" + >>> p.save() + >>> r = p.revisions.get(revision=0) + >>> r.resolve() + >>> r.name + u'Test Persona' + >>> r.description + u'Thos is a test.' + >>> r.url + u'http://www.blarg.com' + """ + + persona = self.revision_of + futureRevs = persona.revisions.filter(revision__gt=self.revision) + attrsLeft = [ attr for attr in Persona.VERSIONED_PROPERTIES + if getattr(self, attr) == None ] + for rev in futureRevs: + attrsFound = [] + for attr in attrsLeft: + if getattr(rev, "has_%s" % attr): + setattr(self, attr, getattr(rev, attr)) + attrsFound.append(attr) + if attrsFound: + attrsLeft = [ attr for attr in attrsLeft + if attr not in attrsFound ] + if not attrsLeft: + break + for attr in attrsLeft: + setattr(self, attr, getattr(persona, attr)) + + def save(self): + """ + The save method for a Revision can only be called once, + because Revision objects are meant to be immutable: + + >>> p = Persona(name='Test Persona', + ... url='http://www.blah.com', + ... category=Category.objects.get(name='Other')) + >>> p.save() + >>> p.description = 'This is a test.' + >>> p.save() + >>> r = p.revisions.get(revision=0) + >>> r.status = "deleted" + >>> r.save() + Traceback (most recent call last): + ... + AssertionError: Revisions are immutable + """ + + if self.id == None: + super(Revision, self).save() + else: + raise AssertionError("Revisions are immutable")
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/personasbackend/personas/sections.py Wed Apr 02 11:59:58 2008 -0700 @@ -0,0 +1,69 @@ +from django.core import urlresolvers +from django.contrib.sites.models import Site + +class Sections( object ): + def __init__( self, *sections ): + self.sections = sections + self.sidebar_entries = [] + self.views = {} + self.names = {} + for section in self.sections: + if section.in_sidebar: + self.sidebar_entries.append( section ) + assert section.name not in self.names + self.names[section.name] = section + assert section.view not in self.views + self.views[section.view] = section + + curr_section = section + while curr_section.parent_name: + curr_parent = self.names[curr_section.parent_name] + section.parents.append( curr_parent ) + curr_section = curr_parent + +class Section( object ): + def __init__( self, name, view, in_sidebar = False, + parent_name = None ): + self.name = name + self.view = view + self.in_sidebar = in_sidebar + self.parent_name = parent_name + + # This will be filled out by the parent Sections object. + self.parents = [] + + def url( self ): + return urlresolvers.reverse( self.view ) + +sections = Sections( + Section( "Home", + "PersonasBackend.personas.views.home_view", + in_sidebar = True ), + Section( "Browse", + "PersonasBackend.personas.views.list_view", + parent_name = "Home", + in_sidebar = True ), + Section( "Create", + "PersonasBackend.personas.views.new_view", + parent_name = "Home", + in_sidebar = True ), + Section( "Edit", + "PersonasBackend.personas.views.edit_view", + parent_name = "Home" ), + Section( "Log in", + "django.contrib.auth.views.login", + parent_name = "Home" ), + Section( "Log out", + "django.contrib.auth.views.logout", + parent_name = "Home" ) + ) + +def context( request ): + viewfunc, args, kwargs = urlresolvers.resolve( request.path ) + viewname = ".".join( [viewfunc.__module__, + viewfunc.__name__] ) + return { + "site_name" : Site.objects.get_current().name, + "sidebar_entries" : sections.sidebar_entries, + "section" : sections.views.get( viewname, None ) + }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/personasbackend/personas/templates/personas/base.html Wed Apr 02 11:59:58 2008 -0700 @@ -0,0 +1,87 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="Content-Type" + content="text/html; charset=iso-8859-1" /> + <title>{{ section.name }} :: {{ site_name }}</title> + <link rel="stylesheet" + type="text/css" + href="{{ MEDIA_URL }}css/otherpages.css" /> + <link rel="shortcut icon" href="{{ MEDIA_URL }}img/favicon.ico" + type="image/x-icon" /> + </head> +<body> + <div id="content"> + <div id="top"> + + <img src="http://labs.mozilla.com/projects/personas/images/personas-logo-beta.png" + alt="Personas for Firefox" /> + </div> + + <div id="bottom"> + <div><img src="http://labs.mozilla.com/projects/personas/images/otherpages-table-top.png" alt="" /></div> + + <div class="table_middle"> + <div id="sidebar"> + <div class="menu-box"> + <ul> + {% for entry in sidebar_entries %} + {% ifequal entry.name section.name %} + <li class="selected"> + <a href="{{ entry.url }}">{{entry.name}}</a> + </li> + {% else %} + <li><a href="{{ entry.url }}">{{ entry.name }}</a></li> + {% endifequal %} + {% endfor %} + {% if perms.personas.can_publish %} + <li><a href="{% url django.contrib.admin.views.main.index %}" + >Administer</a></li> + {% endif %} + </ul> + </div> + {% if user.is_authenticated %} + <p>Logged in as {{ user.email }}.</p> + <p><a href="{% url logout %}">Log out</a></p> + {% else %} + <a href="https://services.mozilla.com/" >Register</a> | + <a href="{% url login %}">Log in</a> + {% endif %} + </div> + + <div id="section-content"> + <div class="title">{% block title %}{{ section.name }}{% endblock %}</div> + <div class="divider"></div> + + <div class="details"> + {% if messages %} + {% for message in messages %} + <div class="message">{{ message }}</div> + {% endfor %} + {% endif %} + {% block content %}{% endblock %} + </div> + </div> + + <div><img src="http://labs.mozilla.com/projects/personas/images/otherpages-table-foot.png" alt="" /></div> + + </div> + + <div id="footer"> + <div class="labs"> + <a href="http://labs.mozilla.com"><img src="http://labs.mozilla.com/projects/personas/images/mozilla-labs-large.png" alt="Mozilla Labs" border="0" /></a> + + Personas for Firefox is a <a href="http://labs.mozilla.com">Mozilla Labs Project</a>. + </div> + <div class="legal"> + © 2007 Mozilla + <span> + <a href="http://www.mozilla.com/en-US/about/legal.html">Legal Notices</a> | + <a href="http://www.mozilla.com/en-US/privacy-policy.html">Privacy Policy</a> + </span> + </div> + </div> + </div> + </div> +</body> +</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/personasbackend/personas/templates/personas/edit.html Wed Apr 02 11:59:58 2008 -0700 @@ -0,0 +1,10 @@ +{% extends "personas/base.html" %} + +{% block content %} +<form enctype="multipart/form-data" method="post" action="."> + <table class="persona-form corner-box"> + {{ form }} + </table> + <input type="submit" class="amo-submit" value="Submit"/> +</form> +{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/personasbackend/personas/templates/personas/home.html Wed Apr 02 11:59:58 2008 -0700 @@ -0,0 +1,14 @@ +{% extends "personas/base.html" %} + +{% block title %}What are Personas?{% endblock %} + +{% block content %} +<p>Personas for Firefox is an extension that adds lightweight theming to your browser.</p> +<p>Personas is a prototype that builds upon the ideas that:</p> +<ul> +<li>themes today are too hard to find, install and use</li> +<li>graphic designers should be able to style the browser without having to code</li> +<li>browsers can be more than just desktop software, they can include online components</li> +<li>people just want their computer to be a little more fun and personal</li> +</ul> +{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/personasbackend/personas/templates/personas/legacy_persona.xul Wed Apr 02 11:59:58 2008 -0700 @@ -0,0 +1,17 @@ +<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + flex="1" + style="background-repeat: no-repeat;" + onload="document.documentElement.style.backgroundImage = 'url({{image}})'"> + + <!-- Because CSS image loads don't block the load/pageshow events in Firefox 2, + - we load the image in an image tag, which does block those events, and then + - set the background-image property once the image has finished loading. --> + <image id="image" collapsed="true"/> + + <script type="application/javascript;version=1.7"> + <![CDATA[ + document.getElementById("image").setAttribute("src", "{{image}}"); + document.documentElement.style.backgroundPosition = "{{position}}"; + ]]> + </script> +</window>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/personasbackend/personas/templates/personas/list.html Wed Apr 02 11:59:58 2008 -0700 @@ -0,0 +1,66 @@ +{% extends "personas/base.html" %} + +{% block content %} +{% if personas %} +<p>Here's a list of all available Personas.</p> +<p>If you have the Personas extension installed, just mouseover the +preview image for a Persona to preview it—when your mouse moves +away from the image, your original Persona will replace the preview.</p> +<p>If you like the Persona, you can click on the preview image to set it +as your current Persona.</p> +<p>Enjoy!</p> +<script> +function dispatchPersonaEvent(aType, aNode, aUrl) { + if (aUrl) { + /* TODO: We should only do this if the Persona is successfully + set, i.e. if the user actually has Personas installed, etc. */ + /* TODO: We should probably just use a library like jQuery to + do this for us. */ + var request = new XMLHttpRequest(); + /* TODO: Be reasonable and make this a POST, as this 'ping' will + change the server's state. */ + request.open( "GET", aUrl, true ); + request.onreadystatechange = function() {} + request.send(null); + } + + var event = document.createEvent("Events"); + event.initEvent(aType, true, false); + aNode.dispatchEvent(event); +} +</script> +{% for persona in personas %} +<div class="corner-box"> + <div onclick="dispatchPersonaEvent('SelectPersona', + event.originalTarget, + '{% url report-selection persona.id %}')" + onmouseover="dispatchPersonaEvent('PreviewPersona', + event.originalTarget)" + onmouseout="dispatchPersonaEvent('ResetPersona', + event.originalTarget)"> + <img persona="{{ persona.json_id }}" + category="{{ persona.category.json_id }}" + src="{{ persona.get_header_url }}" class="preview-image" + width="300" height="20" alt="" /> + </div> + <div class="persona-title"> + <h2 class="persona-name">{{ persona.name }}</h2> + {% if persona.owner %} + <span class="developer"> by {{ persona.owner.first_name }} + {{ persona.owner.last_name }}</span> + {% endif %} + </div> + <div class="persona-desc">{{ persona.description|safe }}</div> + {% if perms.personas.can_publish %} + <a href="{% url django.contrib.admin.views.main.change_stage "personas","persona",persona.id %}">Edit</a> + {% else %} + {% ifequal persona.owner user %} + <a href="{% url edit-persona persona.id %}">Edit</a> + {% endifequal %} + {% endif %} +</div> +{% endfor %} +{% else %} +<p>There are currently no personas available.</p> +{% endif %} +{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/personasbackend/personas/templates/personas/logged_out.html Wed Apr 02 11:59:58 2008 -0700 @@ -0,0 +1,5 @@ +{% extends "personas/base.html" %} + +{% block content %} +<p>{{ title }}</p> +{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/personasbackend/personas/templates/personas/login.html Wed Apr 02 11:59:58 2008 -0700 @@ -0,0 +1,21 @@ +{% extends "personas/base.html" %} + +{% block content %} +{% if form.has_errors %} +<p>Your username and password didn't match. Please try again.</p> +{% endif %} +<form method="post" action="." class="persona-form corner-box"> + <table> + <tr> + <td><label for="id_username">Username:</label></td> + <td>{{ form.username }}</td> + </tr> + <tr> + <td><label for="id_password">Password:</label></td> + <td>{{ form.password }}</td> + </tr> + </table> + <input type="submit" class="amo-submit" value="Log in" /> + <input type="hidden" name="next" value="{{ next }}" /> +</form> +{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/personasbackend/personas/templates/personas/todo.html Wed Apr 02 11:59:58 2008 -0700 @@ -0,0 +1,5 @@ +{% extends "personas/base.html" %} + +{% block content %} +This page is under construction. +{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/personasbackend/personas/tests.py Wed Apr 02 11:59:58 2008 -0700 @@ -0,0 +1,54 @@ +import unittest +import datetime + +from django.test.client import Client +from django.core.urlresolvers import reverse +from PersonasBackend.personas import models + +class JsonTests( unittest.TestCase ): + def setUp( self ): + for persona in models.Persona.objects.all(): + persona.delete() + self.cat = models.Category( name = "Random Things" ) + self.cat.save() + self.persona = models.Persona( + name = "Test Persona", + category = self.cat, + url = "http://www.blarg.com/mypersona", + status = "published" + ) + self.persona.save() + + def tearDown( self ): + self.persona.delete() + self.cat.delete() + + def testCategoriesWorks( self ): + # Just a smoke test to make sure nothing crashes... + client = Client() + response = client.get( reverse("personas-categories-json") ) + assert response.status_code == 200 + + def testAllPersonasWorks( self ): + # Just a smoke test to make sure nothing crashes... + client = Client() + response = client.get( reverse("personas-all-json") ) + assert response.status_code == 200 + + def testPublishDateIsUpdatedProperly( self ): + p = models.Persona( + name='Yet Another Test Persona', + url='http://www.test.com/testpersona', + category=models.Category.objects.get(name='Other')) + + p.save() + self.assertEquals( p.status, "unpublished" ) + self.assertEquals( p.date_published, None ) + + p.status = "published" + now = datetime.datetime.now() + p.save() + assert p.date_published >= now + +if __name__ == "__main__": + unittest.main()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/personasbackend/personas/urls.py Wed Apr 02 11:59:58 2008 -0700 @@ -0,0 +1,49 @@ +from django.conf.urls.defaults import * + +urlpatterns = patterns('', + # JSON feeds + + # TODO: Replace the '.+' at the beginning of these with + # a real regexp that conveys the locale to the view. + url(r'^.+/personas_categories.dat$', + 'PersonasBackend.personas.json_feeds.categories', + name='personas-categories-json'), + url(r'^.+/personas_all.dat$', + 'PersonasBackend.personas.json_feeds.personas', + name='personas-all-json'), + + # Dynamic wrappers for views + url(r'^legacy/(?P<name>.+)$', + 'PersonasBackend.personas.views.legacy_cbeard_persona', + name='legacy-cbeard-persona'), + + # Auth + url(r'^login/$', 'django.contrib.auth.views.login', + {'template_name':'personas/login.html'}, + name='login'), + url(r'^logout/$', 'django.contrib.auth.views.logout', + {'template_name':'personas/logged_out.html'}, + name='logout'), + + # AJAX calls + url(r'^ajax/report_selection/(?P<persona_id>\d+)/$', + 'PersonasBackend.personas.ajax.report_selection', + name='report-selection'), + + # Personas UI + url(r'^new/$', + 'PersonasBackend.personas.views.new_view', + name='new-persona'), + url(r'^(?P<persona_id>\d+)/edit/$', + 'PersonasBackend.personas.views.edit_view', + name='edit-persona'), + url(r'^list/$', 'PersonasBackend.personas.views.list_view', + name='list-personas'), + url(r'^$', 'PersonasBackend.personas.views.home_view', + name='personas-home'), + + # 'Fake' scaffolding view for pages that still need to be + # constructed. + url(r'^TODO/$', 'PersonasBackend.personas.views.todo_view', + name='TODO'), +)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/personasbackend/personas/views.py Wed Apr 02 11:59:58 2008 -0700 @@ -0,0 +1,101 @@ +from django.http import HttpResponseRedirect, HttpResponseForbidden +from django.http import HttpResponse, HttpResponseBadRequest +from django.template import RequestContext +from django.contrib.auth.decorators import login_required +from django.core.urlresolvers import reverse +from django.shortcuts import render_to_response, get_object_or_404 + +from PersonasBackend.personas import models +from PersonasBackend.personas import forms + +def legacy_cbeard_persona( request, name ): + PREFIX = "http://sm-labs01.mozilla.org/legacy-personas/" + FOOTER_URL = "%(prefix)s%(name)s/stbar-%(name)s.jpg" + HEADER_URL = "%(prefix)s%(name)s/tbox-%(name)s.jpg" + + urldict = {"prefix" : PREFIX, "name" : name} + + action = request.GET.get( "action", "" ) + + if action == "footer": + position = "bottom left" + img_src = FOOTER_URL % urldict + elif action == "header": + position = "top right" + img_src = HEADER_URL % urldict + else: + return HttpResponseBadRequest( "Invalid or unsupported action: %s" % + action ) + + return render_to_response( + "personas/legacy_persona.xul", + { "image" : img_src, "position" : position }, + mimetype = "application/vnd.mozilla.xul+xml" + ) + +def list_view( request ): + personas = models.Persona.objects.filter( status="published" ) + return render_to_response( + "personas/list.html", + { "personas" : personas, + "title" : "Browse Personas" }, + context_instance = RequestContext(request) + ) + +def home_view( request ): + return render_to_response( + "personas/home.html", + { "title" : "Home" }, + context_instance = RequestContext(request) + ) + +def todo_view( request ): + return render_to_response( + "personas/todo.html", + { "title" : "Under Construction" }, + context_instance = RequestContext(request) + ) + +def new_view( request ): + return edit_view( request ) + +@login_required +def edit_view( request, persona_id=None ): + if persona_id is None: + persona = None + pageTitle = "Create a new Persona" + else: + persona = get_object_or_404( models.Persona, id=persona_id ) + if not persona.can_user_edit( request.user ): + return HttpResponseForbidden( + "<h1>You do not have permission to edit " + "this Persona.</h1>" + ) + pageTitle = "Edit Persona" + + if request.method == "POST": + form = forms.PersonaForm( request.POST, + instance=persona ) + if form.is_valid(): + newPersona = form.save( commit=False ) + newPersona.save( updater = request.user ) + if persona is None: + msgText = ("Persona created successfully. It will need " + "to be reviewed by a staff member " + "before it is published.") + else: + msgText = ("Persona edited successfully. Your changes " + "will need to be approved by a staff member " + "before they can take effect.") + request.user.message_set.create( message = msgText ) + url = reverse("edit-persona", args=[newPersona.id]) + return HttpResponseRedirect( url ) + else: + form = forms.PersonaForm( instance=persona ) + + return render_to_response( + "personas/edit.html", + { "form" : form, + "title" : pageTitle }, + context_instance = RequestContext(request) + )
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/personasbackend/settings.py Wed Apr 02 11:59:58 2008 -0700 @@ -0,0 +1,109 @@ +# Django settings for PersonasBackend project. + +import os + +myPath = os.path.abspath( os.path.dirname( __file__ ) ) + +DEBUG = True +TEMPLATE_DEBUG = DEBUG + +ADMINS = ( + # ('Your Name', 'your_email@domain.com'), +) + +MANAGERS = ADMINS + +DATABASE_ENGINE = 'sqlite3' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'ado_mssql'. +DATABASE_NAME = os.path.join( myPath, "temp_db" ) # Or path to database file if using sqlite3. +DATABASE_USER = '' # Not used with sqlite3. +DATABASE_PASSWORD = '' # Not used with sqlite3. +DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3. +DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3. + +# Local time zone for this installation. Choices can be found here: +# http://www.postgresql.org/docs/8.1/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE +# although not all variations may be possible on all operating systems. +# If running in a Windows environment this must be set to the same as your +# system time zone. +TIME_ZONE = 'America/Chicago' + +# Language code for this installation. All choices can be found here: +# http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes +# http://blogs.law.harvard.edu/tech/stories/storyReader$15 +LANGUAGE_CODE = 'en-us' + +SITE_ID = 1 + +# If you set this to False, Django will make some optimizations so as not +# to load the internationalization machinery. +USE_I18N = True + +# Absolute path to the directory that holds media. +# Example: "/home/media/media.lawrence.com/" +MEDIA_ROOT = os.path.normpath( os.path.join( myPath, "..", "media" ) ) + +BASE_DIR = "personas/" + +# URL that handles the media served from MEDIA_ROOT. +# Example: "http://media.lawrence.com" +MEDIA_URL = '/%smedia/' % BASE_DIR + +# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a +# trailing slash. +# Examples: "http://foo.com/media/", "/media/". +ADMIN_MEDIA_PREFIX = '/%sadmin/media/' % BASE_DIR + +# Make this unique, and don't share it with anybody. +SECRET_KEY = 'x=0z4lnv#vws4p4a%r(fb=(wh&o4k)k!5!a9b*3-j7s87^v43d' + +# List of callables that know how to import templates from various sources. +TEMPLATE_LOADERS = ( + 'django.template.loaders.filesystem.load_template_source', + 'django.template.loaders.app_directories.load_template_source', +# 'django.template.loaders.eggs.load_template_source', +) + +MIDDLEWARE_CLASSES = ( + 'django.middleware.cache.CacheMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.middleware.doc.XViewMiddleware', +) + +LOGIN_URL = '/%slogin/' % BASE_DIR +LOGIN_REDIRECT_URL = '/%s' % BASE_DIR + +ROOT_URLCONF = 'PersonasBackend.urls' + +TEMPLATE_DIRS = ( + # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". + # Always use forward slashes, even on Windows. + # Don't forget to use absolute paths, not relative paths. + os.path.normpath( os.path.join( myPath, "..", "templates" ) ), +) + +INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.sites', + 'django.contrib.admin', + 'PersonasBackend.personas', +) + +TEMPLATE_CONTEXT_PROCESSORS = ( + "django.core.context_processors.auth", + "django.core.context_processors.debug", + "django.core.context_processors.i18n", + "django.core.context_processors.media", + "PersonasBackend.personas.sections.context", +) + +CACHE_BACKEND = 'locmem:///' +CACHE_MIDDLEWARE_SECONDS = 5 +CACHE_MIDDLEWARE_KEY_PREFIX = "personas" + +AUTHENTICATION_BACKENDS = ( + "PersonasBackend.weaveproxyauth.Backend", +)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/personasbackend/urls.py Wed Apr 02 11:59:58 2008 -0700 @@ -0,0 +1,28 @@ +import os + +from django.conf.urls.defaults import * +from PersonasBackend import settings +import django.contrib.admin + +urlpatterns = patterns('', + # Admin media + # TODO: Remove the static.serve, b/c it's supposedly insecure. + (r'^%sadmin/media/(?P<path>.*)$' % settings.BASE_DIR, + 'django.views.static.serve', + {'document_root': os.path.join( django.contrib.admin.__path__[0], + "media" )}), + + # Admin + (r'^%sadmin/' % settings.BASE_DIR, + include('django.contrib.admin.urls')), + + # Personas media + # TODO: Remove the static.serve, b/c it's supposedly insecure. + (r'^%smedia/(?P<path>.*)$' % settings.BASE_DIR, + 'django.views.static.serve', + {'document_root': settings.MEDIA_ROOT}), + + # Personas + (r'^%s' % settings.BASE_DIR, + include('PersonasBackend.personas.urls')), +)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/personasbackend/utils.py Wed Apr 02 11:59:58 2008 -0700 @@ -0,0 +1,8 @@ +from django.contrib.sites.models import Site + +def make_absolute_url( path ): + domain = Site.objects.get_current().domain + if domain == "localhost": + domain = "localhost:8000" + url = "http://%s%s" % (domain, path) + return url
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/personasbackend/weaveproxyauth.py Wed Apr 02 11:59:58 2008 -0700 @@ -0,0 +1,59 @@ +import sha +import urllib2 +import httplib + +from django.contrib.auth.models import User + +class Backend(object): + def authenticate(self, username=None, password=None): + hexuser = sha.sha(username).hexdigest() + url = "https://services.mozilla.com/user/%s/" % hexuser + authHandler = urllib2.HTTPBasicAuthHandler() + authHandler.add_password("services.mozilla.com - proxy", + "services.mozilla.com", + username, + password) + + opener = urllib2.build_opener(authHandler) + + try: + obj = opener.open(url) + obj.read() + auth_successful = True + except urllib2.HTTPError, e: + if e.code == httplib.UNAUTHORIZED: + auth_successful = False + else: + raise + + if auth_successful: + try: + user = User.objects.get(email=username) + except User.DoesNotExist: + # We have to go through this annoyance because Django + # auth requires us to enter a username, and the username + # can be no more than 30 characters and can't include + # anything other than alphanumeric characters. + munged_username = "".join( + [char for char in username if char.isalnum()] + )[:25] + + offset = 0 + while User.objects.filter( + username = munged_username + str(offset) + ): + offset += 1 + + user = User(username=munged_username + str(offset), + password="Retrieved from Weave", + email=username) + user.save() + return user + + return None + + def get_user(self, user_id): + try: + return User.objects.get(pk=user_id) + except User.DoesNotExist: + return None