[cig-commits] r12009 - in cs/portal/trunk/northridge/SeismoWebPortal: . templates/SeismoWebPortal
leif at geodynamics.org
leif at geodynamics.org
Thu May 22 18:28:08 PDT 2008
Author: leif
Date: 2008-05-22 18:28:08 -0700 (Thu, 22 May 2008)
New Revision: 12009
Modified:
cs/portal/trunk/northridge/SeismoWebPortal/forms.py
cs/portal/trunk/northridge/SeismoWebPortal/mezzanine.py
cs/portal/trunk/northridge/SeismoWebPortal/models.py
cs/portal/trunk/northridge/SeismoWebPortal/templates/SeismoWebPortal/pluggable.html
cs/portal/trunk/northridge/SeismoWebPortal/views.py
Log:
Implemented object ownership (per-user objects). Improved code
sharing by removing the two _manipulate() methods.
Modified: cs/portal/trunk/northridge/SeismoWebPortal/forms.py
===================================================================
--- cs/portal/trunk/northridge/SeismoWebPortal/forms.py 2008-05-23 01:17:14 UTC (rev 12008)
+++ cs/portal/trunk/northridge/SeismoWebPortal/forms.py 2008-05-23 01:28:08 UTC (rev 12009)
@@ -381,17 +381,30 @@
region, created = models.Region.objects.get_or_create(name = new_data['region'])
# Add the Source.
- args = {}
- for k,v in new_data.items():
- args[k] = v
- args['event'] = event
- args['dataSource'] = dataSource
- args['region'] = region
- args['when'] = datetime.combine(args['when_date'], args['when_time'])
- del args['name']
- del args['when_date']
- del args['when_time']
- source = models.Source.objects.create(**args)
+ source = models.Source.objects.create(
+ event = event,
+ dataSource = dataSource,
+ when = datetime.combine(new_data['when_date'], new_data['when_time']),
+ microsecond = new_data['microsecond'],
+ sourceLatitude = new_data['sourceLatitude'],
+ sourceLongitude = new_data['sourceLongitude'],
+ sourceDepth = new_data['sourceDepth'],
+ sourceMB = new_data['sourceMB'],
+ sourceMs = new_data['sourceMs'],
+ region = region,
+ eventName = new_data['eventName'],
+ timeShift = new_data['timeShift'],
+ halfDuration = new_data['halfDuration'],
+ latitude = new_data['latitude'],
+ longitude = new_data['longitude'],
+ depth = new_data['depth'],
+ Mrr = new_data['Mrr'],
+ Mtt = new_data['Mtt'],
+ Mpp = new_data['Mpp'],
+ Mrt = new_data['Mrt'],
+ Mrp = new_data['Mrp'],
+ Mtp = new_data['Mtp'],
+ )
return event
Modified: cs/portal/trunk/northridge/SeismoWebPortal/mezzanine.py
===================================================================
--- cs/portal/trunk/northridge/SeismoWebPortal/mezzanine.py 2008-05-23 01:17:14 UTC (rev 12008)
+++ cs/portal/trunk/northridge/SeismoWebPortal/mezzanine.py 2008-05-23 01:28:08 UTC (rev 12009)
@@ -3,6 +3,7 @@
from django import oldforms
from django.db.models import FileField
from django.contrib.auth.views import redirect_to_login
+from django.contrib.contenttypes.models import ContentType
from django.template import loader, Context
from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.core.exceptions import ObjectDoesNotExist
@@ -28,7 +29,7 @@
@classmethod
def create(cls, request, template_name=None,
template_loader=loader, extra_context=None, post_save_redirect=None,
- login_required=False):
+ login_required=False, manipulator=None):
"""
Generic object-creation function.
@@ -42,7 +43,8 @@
if login_required and not request.user.is_authenticated():
return redirect_to_login(request.path)
- manipulator = cls.addManipulator()
+ if manipulator is None:
+ manipulator = cls.addManipulator()
if request.POST:
# If data was POSTed, we're trying to create a new object
new_data = request.POST.copy()
@@ -57,6 +59,8 @@
if not errors:
# No errors -- this means we can save the data!
new_object = manipulator.save(new_data)
+
+ models.Ownership.objects.create(owner = request.user, obj = new_object)
if request.user.is_authenticated():
request.user.message_set.create(message = 'Created "%s".' % new_object)
@@ -205,7 +209,7 @@
return t.render(c)
@classmethod
- def list(cls, request, paginate_by=None, page=None,
+ def list(cls, request, l, paginate_by=None, page=None,
allow_empty=True, template_name=None, template_loader=loader,
extra_context=None, template_object_name='object',
):
@@ -243,10 +247,8 @@
"""
if extra_context is None: extra_context = {}
- queryset = cls.Model.objects.all()
- queryset = queryset._clone()
if paginate_by:
- paginator = ObjectPaginator(queryset, paginate_by)
+ paginator = ObjectPaginator(l, paginate_by)
if not page:
page = request.GET.get('page', 1)
try:
@@ -274,11 +276,11 @@
})
else:
c = Context({
- '%s_list' % template_object_name: queryset,
+ '%s_list' % template_object_name: l,
'is_paginated': False,
'root': request.root,
})
- if not allow_empty and len(queryset) == 0:
+ if not allow_empty and len(l) == 0:
raise Http404
for key, value in extra_context.items():
if callable(value):
@@ -286,7 +288,7 @@
else:
c[key] = value
if not template_name:
- model = queryset.model
+ model = cls.Model
template_name = "%s/%s_list.html" % (model._meta.app_label, model._meta.object_name.lower())
t = template_loader.get_template(template_name)
return t.render(c)
@@ -327,6 +329,7 @@
def duplicate(self, request):
dup = self._duplicate()
+ models.Ownership.objects.create(owner = self.owner, obj = dup)
if request.user.is_authenticated():
request.user.message_set.create(message = 'Editing a new copy of "%s".' % self.obj)
return HttpResponseRedirect(self.urlForObject(dup, request.root, action = 'edit'))
@@ -341,9 +344,10 @@
dup.save()
return dup
- def __init__(self, objId):
+ def __init__(self, objId, owner):
self.objId = objId
self.obj = self._lookupObject()
+ self.owner = owner
return
def _lookupObject(self):
@@ -378,6 +382,7 @@
if not errors:
manipulator.do_html2python(new_data)
new_object = manipulator.save(new_data)
+ models.Ownership.objects.create(owner = request.user, obj = new_object)
if request.user.is_authenticated():
request.user.message_set.create(message = 'Uploaded "%s".' % new_object)
if post_save_redirect:
@@ -400,33 +405,28 @@
return t.render(c)
id = property(lambda self: self.obj.id)
- prevObject = property(lambda self: self._getPrevObject())
- nextObject = property(lambda self: self._getNextObject())
- def _getPrevObject(self):
- if not hasattr(self, '_prevObject'):
- self._prevObject = None
- prevObjQ = self._prevObjectQuery()
- for o in prevObjQ:
- self._prevObject = o
- break
- return self._prevObject
+ @classmethod
+ def objectList(cls, owner):
+ ctype = ContentType.objects.get_for_model(cls.Model)
+ return [o.obj for o in models.Ownership.objects.filter(owner = owner, objType = ctype)]
- def _prevObjectQuery(self):
- return self.Model.objects.filter(id__lt = self.obj.id).order_by('-id')
-
- def _getNextObject(self):
- if not hasattr(self, '_nextObject'):
- self._nextObject = None
- nextObjQ = self._nextObjectQuery()
- for o in nextObjQ:
- self._nextObject = o
- break
- return self._nextObject
+ def navigation(self):
+ prevObject = None
+ nextObject = None
+ l = self.objectList(self.owner)
+ i = l.index(self.obj)
+ if i > 0:
+ prevObject = l[i - 1]
+ i += 1
+ if i < len(l):
+ nextObject = l[i]
+ return dict(index = i,
+ count = len(l),
+ prevObject = prevObject,
+ nextObject = nextObject,
+ )
- def _nextObjectQuery(self):
- return self.Model.objects.filter(id__gt = self.obj.id).order_by('id')
-
@classmethod
def urlForObject(cls, obj, root, action=None):
if action:
@@ -463,44 +463,35 @@
@classmethod
def create(cls, request):
+ return super(Event, cls).create(
+ request,
+ template_name = cls.singleSourceFormTemplateName(),
+ )
+
+ def update(self, request):
+ if self.obj.singleSource:
+ return super(Event, self).update(
+ request,
+ template_name = self.singleSourceFormTemplateName(),
+ )
+ return super(Event, self).update(request)
+
+ @classmethod
+ def addManipulator(cls):
from forms import SingleSourceEventAddManipulator
- return cls._manipulate(request, SingleSourceEventAddManipulator(), 'Created "%s".')
+ return SingleSourceEventAddManipulator()
- def update(self, request):
+ def changeManipulator(self):
from forms import SingleSourceEventChangeManipulator
event = self.obj
- if not event.singleSource:
- return super(Event, self).update(request)
- return self._manipulate(request, SingleSourceEventChangeManipulator(event), 'Saved "%s".', event)
+ if event.singleSource:
+ return SingleSourceEventChangeManipulator(event)
+ return super(Event, self).changeManipulator()
@classmethod
- def _manipulate(cls, request, manipulator, messageFormat, event=None):
- if request.method == 'POST':
- new_data = request.POST.copy()
- errors = manipulator.get_validation_errors(new_data)
- if not errors:
- manipulator.do_html2python(new_data)
- new_data['class'] = None; del new_data['class']
- new_data['object'] = None; del new_data['object']
- new_data['action'] = None; del new_data['action']
- obj = manipulator.save(new_data)
- if request.user.is_authenticated():
- request.user.message_set.create(message = messageFormat % obj)
- return HttpResponseRedirect(cls.urlForObject(obj, request.root))
- else:
- new_data = manipulator.flatten_data()
- errors = {}
+ def singleSourceFormTemplateName(cls):
+ return 'SeismoWebPortal/single_source_event_form.html'
- form = oldforms.FormWrapper(manipulator, new_data, errors)
- t = loader.get_template('SeismoWebPortal/single_source_event_form.html')
- c = Context(dict(
- form = form,
- action = request.path,
- object = event,
- root = request.root,
- ))
- return t.render(c)
-
def _duplicate(self):
from copy import copy
dup = super(Event, self)._duplicate()
@@ -603,11 +594,32 @@
)
return response
- def _prevObjectQuery(self):
- return self.obj.event.source_set.filter(timeShift__lte = self.obj.timeShift, id__lt = self.obj.id).order_by('-timeShift', '-id')
-
- def _nextObjectQuery(self):
- return self.obj.event.source_set.filter(timeShift__gte = self.obj.timeShift, id__gt = self.obj.id).order_by('timeShift', 'id')
+ def navigation(self):
+ neighbors = []
+ queries = [
+ self.obj.event.source_set.filter(timeShift__lte = self.obj.timeShift).order_by('-timeShift', '-id'),
+ self.obj.event.source_set.filter(timeShift__gte = self.obj.timeShift).order_by('timeShift', 'id'),
+ ]
+ i = None
+ for q in queries:
+ neighbor = None
+ sawSelf = False
+ tally = 0
+ for o in q:
+ if o.id == self.obj.id:
+ sawSelf = True
+ if i is None:
+ i = q.count() - tally
+ elif sawSelf:
+ neighbor = o
+ break
+ tally += 1
+ neighbors.append(neighbor)
+ return dict(index = i,
+ count = self.obj.event.sources().count(),
+ prevObject = neighbors[0],
+ nextObject = neighbors[1],
+ )
# support code
@@ -706,7 +718,6 @@
@classmethod
def create(cls, request):
- from forms import MeshAddManipulator
nchunks = request.REQUEST.get('nchunks')
if nchunks is None:
raise Http404
@@ -714,17 +725,33 @@
nchunks = int(nchunks)
except ValueError:
raise Http404
- return cls._manipulate(request, nchunks, MeshAddManipulator(nchunks), 'Created "%s".')
+ return super(Specfem3DGlobeMesh, cls).create(
+ request,
+ template_name = cls.formTemplateName(nchunks),
+ extra_context = { 'nchunks': nchunks },
+ manipulator = cls.addManipulator(nchunks),
+ )
def update(self, request):
+ nchunks = self.obj.nchunks
+ return super(Specfem3DGlobeMesh, self).update(
+ request,
+ template_name = self.formTemplateName(nchunks),
+ extra_context = { 'nchunks': nchunks },
+ )
+
+ @classmethod
+ def addManipulator(cls, nchunks):
+ from forms import MeshAddManipulator
+ return MeshAddManipulator(nchunks)
+
+ def changeManipulator(self):
from forms import MeshChangeManipulator
mesh = self.obj
- nchunks = mesh.nchunks
- return self._manipulate(request, nchunks, MeshChangeManipulator(nchunks, mesh.id), 'Saved "%s".', mesh)
+ return MeshChangeManipulator(mesh.nchunks, mesh.id)
@classmethod
- def _manipulate(cls, request, nchunks, manipulator, messageFormat, mesh=None):
-
+ def formTemplateName(cls, nchunks):
if nchunks == 1:
template = 'SeismoWebPortal/mesh_form_1chunk.html'
elif nchunks == 2:
@@ -735,34 +762,9 @@
template = 'SeismoWebPortal/mesh_form_global.html'
else:
assert False
+ return template
- if request.method == 'POST':
- new_data = request.POST.copy()
- errors = manipulator.get_validation_errors(new_data)
- if not errors:
- manipulator.do_html2python(new_data)
- new_object = manipulator.save(new_data)
- if request.user.is_authenticated():
- request.user.message_set.create(message = messageFormat % new_object)
- return HttpResponseRedirect(cls.urlForObject(new_object, request.root))
- else:
- # Populate new_data with a 'flattened' version of the current data.
- new_data = manipulator.flatten_data()
- errors = {}
- # Populate the FormWrapper.
- form = oldforms.FormWrapper(manipulator, new_data, errors)
- t = loader.get_template(template)
- c = Context(dict(
- form = form,
- nchunks = nchunks,
- object = mesh,
- action = request.path,
- root = request.root,
- ))
- return t.render(c)
-
-
class Specfem3DGlobeParameters(Object):
Model = models.Specfem3DGlobeParameters
Modified: cs/portal/trunk/northridge/SeismoWebPortal/models.py
===================================================================
--- cs/portal/trunk/northridge/SeismoWebPortal/models.py 2008-05-23 01:17:14 UTC (rev 12008)
+++ cs/portal/trunk/northridge/SeismoWebPortal/models.py 2008-05-23 01:28:08 UTC (rev 12009)
@@ -493,4 +493,24 @@
list_filter = ('approved',)
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# Object Grouping
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+class Ownership(models.Model):
+
+ owner = models.ForeignKey(User, db_index=True)
+
+ objType = models.ForeignKey(ContentType, db_index=True)
+ objId = models.PositiveIntegerField(db_index=True)
+ obj = models.GenericForeignKey(ct_field='objType', fk_field='objId')
+
+
+class BuiltIn(models.Model):
+ objType = models.ForeignKey(ContentType, db_index=True)
+ objId = models.PositiveIntegerField(db_index=True)
+ obj = models.GenericForeignKey(ct_field='objType', fk_field='objId')
+
+
# end of file
Modified: cs/portal/trunk/northridge/SeismoWebPortal/templates/SeismoWebPortal/pluggable.html
===================================================================
--- cs/portal/trunk/northridge/SeismoWebPortal/templates/SeismoWebPortal/pluggable.html 2008-05-23 01:17:14 UTC (rev 12008)
+++ cs/portal/trunk/northridge/SeismoWebPortal/templates/SeismoWebPortal/pluggable.html 2008-05-23 01:28:08 UTC (rev 12009)
@@ -173,6 +173,15 @@
<tr>
<td>
{% if object %}
+ {{ index }} of {{ count }}
+ {% else %}
+ {% ifnotequal count None %}
+ {{ count }} items
+ {% endifnotequal %}
+ {% endif %}
+ </td>
+ <td>
+ {% if object %}
{% ifequal klass 'Source' %}
<a href="{{root}}/?class=Event&object={{object.obj.event.id}}#s{{object.id}}"><img src="{{root}}/images/highlight-item.gif" alt="Highlight Item" width=24 height=16></a>
{% else %}
Modified: cs/portal/trunk/northridge/SeismoWebPortal/views.py
===================================================================
--- cs/portal/trunk/northridge/SeismoWebPortal/views.py 2008-05-23 01:17:14 UTC (rev 12008)
+++ cs/portal/trunk/northridge/SeismoWebPortal/views.py 2008-05-23 01:28:08 UTC (rev 12009)
@@ -32,22 +32,10 @@
return render_to_response('SeismoWebPortal/splash.html', {'root': root},
RequestContext(request, {}))
- className = request.REQUEST.get('class')
- Class = None
- obj = None
ret = None
- creatable = False
- uploadable = False
- downloadable = False
- downloadableAsText = False
- downloadableAsKML = False
- duplicatable = False
- views = []
- activeView = None
- prevObject = None
- nextObject = None
- klass = None
+ c = {}
+ className = request.REQUEST.get('class')
if className is None:
t = loader.get_template('SeismoWebPortal/home.html')
ret = t.render({})
@@ -64,7 +52,9 @@
if objId is None:
if action is None:
- ret = Class.list(request)
+ l = Class.objectList(request.user)
+ ret = Class.list(request, l)
+ c['count'] = len(l)
elif action == 'new':
ret = Class.create(request)
elif action == 'upload':
@@ -78,18 +68,22 @@
except ValueError:
raise Http404
- obj = Class(objId)
- downloadableAsText = obj.downloadableAsText
- downloadableAsKML = obj.downloadableAsKML
- downloadable = downloadableAsText or downloadableAsKML
- duplicatable = obj.duplicatable
- views = obj.views
- prevObject = obj.prevObject
- nextObject = obj.nextObject
+ obj = Class(objId, request.user)
+ c.update(dict(
+ object = obj,
+ # menus/buttons
+ downloadableAsText = obj.downloadableAsText,
+ downloadableAsKML = obj.downloadableAsKML,
+ downloadable = obj.downloadableAsText or obj.downloadableAsKML,
+ duplicatable = obj.duplicatable,
+ views = obj.views,
+ ))
+ c.update(obj.navigation())
if action is None:
activeView = request.REQUEST.get('view', obj.defaultView)
ret = obj.detail(request, activeView)
+ c['activeView'] = activeView
elif action == 'edit':
ret = obj.update(request)
elif action == 'duplicate':
@@ -107,28 +101,19 @@
if isinstance(ret, HttpResponse):
return ret
- creatable = Class.creatable
- uploadable = Class.uploadable
- klass = Class.__name__
-
+ c.update(dict(
+ creatable = Class.creatable,
+ uploadable = Class.uploadable,
+ klass = Class.__name__,
+ ))
+
response = HttpResponse(mimetype='text/html')
t = loader.get_template('SeismoWebPortal/pluggable.html')
- c = RequestContext(request, dict(
+ c.update(dict(
content = ret,
- klass = klass,
- object = obj,
- creatable = creatable,
- uploadable = uploadable,
- downloadable = downloadable,
- downloadableAsText = downloadableAsText,
- downloadableAsKML = downloadableAsKML,
- duplicatable = duplicatable,
- views = views,
- activeView = activeView,
- prevObject = prevObject,
- nextObject = nextObject,
root = root,
))
+ c = RequestContext(request, c)
response.write(t.render(c))
return response
@@ -554,7 +539,7 @@
if isNewUser:
request.session.delete_test_cookie()
notify_managers_of_new_user(request, user)
- user.message_set.create(message="Welcome to the SPECFEM 3D GLOBE web portal!")
+ user.message_set.create(message="Welcome to the CIG Seismology Web Portal!")
else:
user.message_set.create(message="Your contact information has been saved.")
return HttpResponseRedirect("%s/" % root)
More information about the cig-commits
mailing list