[cig-commits] r6218 - in cs/pythia/trunk/opal: components core core/handlers db sites views views/generic

leif at geodynamics.org leif at geodynamics.org
Fri Mar 9 19:09:04 PST 2007


Author: leif
Date: 2007-03-09 19:09:03 -0800 (Fri, 09 Mar 2007)
New Revision: 6218

Added:
   cs/pythia/trunk/opal/components/WebComponent.py
   cs/pythia/trunk/opal/db/queries.py
   cs/pythia/trunk/opal/views/DetailView.py
   cs/pythia/trunk/opal/views/ListView.py
   cs/pythia/trunk/opal/views/PaginatedListView.py
   cs/pythia/trunk/opal/views/View.py
Removed:
   cs/pythia/trunk/opal/views/generic/list_detail.py
Modified:
   cs/pythia/trunk/opal/core/handlers/base.py
   cs/pythia/trunk/opal/core/urlresolvers.py
   cs/pythia/trunk/opal/sites/WebSite.py
   cs/pythia/trunk/opal/views/__init__.py
Log:
Sketched-out OOP-ized object_list and object_detail.  Added the germ
of my idea of how URLResolvers should work.


Added: cs/pythia/trunk/opal/components/WebComponent.py
===================================================================
--- cs/pythia/trunk/opal/components/WebComponent.py	2007-03-10 01:32:55 UTC (rev 6217)
+++ cs/pythia/trunk/opal/components/WebComponent.py	2007-03-10 03:09:03 UTC (rev 6218)
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+#                      California Institute of Technology
+#                        (C) 2007  All Rights Reserved
+#
+# {LicenseText}
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+
+
+from pyre.components import Component
+
+
+class WebComponent(Component):
+
+
+    children = {}
+
+
+    def view(self):
+        return self.DefaultViewClass(self)
+
+
+# end of file

Modified: cs/pythia/trunk/opal/core/handlers/base.py
===================================================================
--- cs/pythia/trunk/opal/core/handlers/base.py	2007-03-10 01:32:55 UTC (rev 6217)
+++ cs/pythia/trunk/opal/core/handlers/base.py	2007-03-10 03:09:03 UTC (rev 6218)
@@ -50,7 +50,7 @@
 
     def get_response(self, path, request):
         "Returns an HttpResponse object for the given HttpRequest"
-        from opal.core import exceptions, urlresolvers
+        from opal.core import exceptions
         from opal.core.mail import mail_admins
         from opal.conf import settings
 
@@ -60,9 +60,9 @@
             if response:
                 return response
 
-        resolver = urlresolvers.RegexURLResolver(r'^/', settings.ROOT_URLCONF)
         try:
-            callback, callback_args, callback_kwargs = resolver.resolve(path)
+            site = settings
+            callback, callback_args, callback_kwargs = site.resolve(path)
 
             # Apply view middleware
             for middleware_method in self._view_middleware:

Modified: cs/pythia/trunk/opal/core/urlresolvers.py
===================================================================
--- cs/pythia/trunk/opal/core/urlresolvers.py	2007-03-10 01:32:55 UTC (rev 6217)
+++ cs/pythia/trunk/opal/core/urlresolvers.py	2007-03-10 03:09:03 UTC (rev 6218)
@@ -217,3 +217,23 @@
         urlconf = settings.ROOT_URLCONF
     resolver = RegexURLResolver(r'^/', urlconf)
     return '/' + resolver.reverse(viewname, *args, **kwargs)
+
+class TreeURLResolver(object):
+    def __init__(self, root):
+        self.root = root
+    
+    def resolve(self, pathname):
+        #raise Resolver404, {'tried': ['foo', 'bar', path], 'path': path + 'hey'}
+        path = pathname.split('/')
+        args = ()
+        kwargs = {}
+        node = self.root
+        try:
+            for name in path[:-1]:
+                node = node.children[name]
+            name = path[-1]
+            if name != "":
+                node = node.children[name]
+        except KeyError:
+            raise Http404
+        return node.view().response, args, kwargs

Added: cs/pythia/trunk/opal/db/queries.py
===================================================================
--- cs/pythia/trunk/opal/db/queries.py	2007-03-10 01:32:55 UTC (rev 6217)
+++ cs/pythia/trunk/opal/db/queries.py	2007-03-10 03:09:03 UTC (rev 6218)
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+#                      California Institute of Technology
+#                        (C) 2007  All Rights Reserved
+#
+# {LicenseText}
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+
+
+class Query(object):
+
+    def apply(self, queryset):
+        raise NotImplementedError()
+
+    def get(self, queryset):
+        queryset = self.apply(queryset)
+        return queryset.get()
+
+
+class ObjectIdQuery(Query):
+
+    def __init__(self, object_id):
+        Query.__init__(self)
+        self.object_id = object_id
+
+    def apply(self, queryset):
+        return queryset.filter(pk=self.object_id)
+
+    def __str__(self):
+        return "object_id=%s" % self.object_id
+
+
+class ObjectSlugQuery(Query):
+
+    def __init__(self, slug, slug_field):
+        Query.__init__(self)
+        self.slug = slug
+        self.slug_field = slug_field
+
+    def apply(self, queryset):
+        return queryset.filter(**{self.slug_field: self.slug})
+
+    def __str__(self):
+        return "%s='%s'" % (self.slug_field, self.slug)
+
+
+def objectQuery(object_id=None, slug=None, slug_field=None):
+    if object_id:
+        query = ObjectIdQuery(object_id)
+    elif slug and slug_field:
+        query = ObjectSlugQuery(slug, slug_field)
+    else:
+        raise AttributeError, "Object query must be created with either an object_id or a slug/slug_field."
+    return query
+
+
+# end of file

Modified: cs/pythia/trunk/opal/sites/WebSite.py
===================================================================
--- cs/pythia/trunk/opal/sites/WebSite.py	2007-03-10 01:32:55 UTC (rev 6217)
+++ cs/pythia/trunk/opal/sites/WebSite.py	2007-03-10 03:09:03 UTC (rev 6218)
@@ -316,7 +316,7 @@
     #########
 
     SITE_ID = pyre.int("site-id", default=1)
-    ROOT_URLCONF = pyre.str("root-urlconf", default="not.yet.implemented")
+    xROOT_URLCONF = pyre.str("root-urlconf", default="not.yet.implemented")
 
 
     def _configure(self):
@@ -333,4 +333,24 @@
         return
 
 
+    ##########
+
+
+    urlpatterns = None
+
+
+    def resolve(self, path):
+        resolver = self.urlResolver()
+        return resolver.resolve(path)
+
+
+    def urlResolver(self):
+        from opal.core import urlresolvers
+        if self.urlpatterns is None:
+            resolver = urlresolvers.TreeURLResolver(self)
+        else:
+            resolver = urlresolvers.RegexURLResolver(r'^/', self)
+        return resolver
+
+
 # end of file

Added: cs/pythia/trunk/opal/views/DetailView.py
===================================================================
--- cs/pythia/trunk/opal/views/DetailView.py	2007-03-10 01:32:55 UTC (rev 6217)
+++ cs/pythia/trunk/opal/views/DetailView.py	2007-03-10 03:09:03 UTC (rev 6218)
@@ -0,0 +1,65 @@
+#!/usr/bin/env python
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+#                      California Institute of Technology
+#                        (C) 2007  All Rights Reserved
+#
+# {LicenseText}
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+
+
+from View import View
+from opal.template import RequestContext
+from opal.http import Http404, HttpResponse
+from opal.core.xheaders import populate_xheaders
+
+
+class DetailView(View):
+    """
+    Generic view of an object.
+
+    Templates: ``<app_label>/<model_name>_detail.html``
+    Context:
+        object
+            the object
+    """
+
+
+    templateNameTag = "detail"
+
+
+    def __init__(self, queryset, query,
+                 template_name_field=None, **kwds):
+        View.__init__(self, queryset=queryset, **kwds)
+        self.query = query
+        self.template_name_field = template_name_field
+        return
+
+
+    def response(self, request):
+        model = self.queryset.model
+        try:
+            obj = self.query.get(self.queryset)
+        except ObjectDoesNotExist:
+            raise Http404, "No %s found matching the query '%s'" % (model._meta.verbose_name, query)
+        t = self.loadTemplate(obj)
+        c = RequestContext(request, {template_object_name: obj}, self.context_processors)
+        c = self.addExtraContext(c)
+        response = HttpResponse(t.render(c), mimetype=self.mimetype)
+        populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.name))
+        return response
+
+
+    def loadTemplate(self, obj):
+        if self.template_name_field:
+            template_name_list = [getattr(obj, self.template_name_field), self.template_name]
+            t = self.template_loader.select_template(template_name_list)
+        else:
+            t = super(DetailView, self).loadTemplate()
+        return t
+
+
+# end of file

Added: cs/pythia/trunk/opal/views/ListView.py
===================================================================
--- cs/pythia/trunk/opal/views/ListView.py	2007-03-10 01:32:55 UTC (rev 6217)
+++ cs/pythia/trunk/opal/views/ListView.py	2007-03-10 03:09:03 UTC (rev 6218)
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+#                      California Institute of Technology
+#                        (C) 2007  All Rights Reserved
+#
+# {LicenseText}
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+
+
+from View import View
+from opal.template import RequestContext
+from opal.http import Http404, HttpResponse
+
+
+class ListView(View):
+    """
+    Generic list of objects.
+
+    Templates: ``<app_label>/<model_name>_list.html``
+    Context:
+        object_list
+            list of objects
+        is_paginated
+            are the results paginated?
+        results_per_page
+            number of objects per page (if paginated)
+        has_next
+            is there a next page?
+        has_previous
+            is there a prev page?
+        page
+            the current page
+        next
+            the next page
+        previous
+            the previous page
+        pages
+            number of pages, total
+        hits
+            number of objects, total
+    """
+
+
+    templateNameTag = "list"
+
+
+    def __init__(self, queryset, allow_empty=True, **kwds):
+        View.__init__(self, queryset=queryset, **kwds)
+        self.allow_empty = allow_empty
+        return
+
+
+    def response(self, request):
+        c = self.requestContext(request)
+        c = self.addExtraContext(c)
+        t = self.loadTemplate()
+        return HttpResponse(t.render(c), mimetype=self.mimetype)
+
+
+    def requestContext(self, request):
+        c = RequestContext(request, {
+            '%s_list' % self.template_object_name: self.queryset,
+            'is_paginated': False
+        }, self.context_processors)
+        if not self.allow_empty and len(self.queryset) == 0:
+            raise Http404
+        return c
+
+
+# end of file

Added: cs/pythia/trunk/opal/views/PaginatedListView.py
===================================================================
--- cs/pythia/trunk/opal/views/PaginatedListView.py	2007-03-10 01:32:55 UTC (rev 6217)
+++ cs/pythia/trunk/opal/views/PaginatedListView.py	2007-03-10 03:09:03 UTC (rev 6218)
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+#                      California Institute of Technology
+#                        (C) 2007  All Rights Reserved
+#
+# {LicenseText}
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+
+
+from ListView import ListView
+from opal.core.paginator import ObjectPaginator, InvalidPage
+from opal.template import RequestContext
+
+
+class PaginatedListView(ListView):
+    """
+    Paginated list of objects.
+
+    Templates: ``<app_label>/<model_name>_list.html``
+    Context:
+        object_list
+            list of objects
+        is_paginated
+            are the results paginated?
+        results_per_page
+            number of objects per page (if paginated)
+        has_next
+            is there a next page?
+        has_previous
+            is there a prev page?
+        page
+            the current page
+        next
+            the next page
+        previous
+            the previous page
+        pages
+            number of pages, total
+        hits
+            number of objects, total
+    """
+
+
+    def __init__(self, queryset, paginate_by, page=None, **kwds):
+        ListView.__init__(queryset=queryset, **kwds)
+        self.paginate_by = paginate_by
+        self.page = page
+        return
+
+
+    def requestContext(self, request):
+        queryset = self.queryset._clone()
+        paginator = ObjectPaginator(queryset, self.paginate_by)
+        page = self.page
+        if not page:
+            page = request.GET.get('page', 1)
+        try:
+            page = int(page)
+            object_list = paginator.get_page(page - 1)
+        except (InvalidPage, ValueError):
+            if page == 1 and self.allow_empty:
+                object_list = []
+            else:
+                raise Http404
+        c = RequestContext(request, {
+            '%s_list' % self.template_object_name: object_list,
+            'is_paginated': paginator.pages > 1,
+            'results_per_page': self.paginate_by,
+            'has_next': paginator.has_next_page(page - 1),
+            'has_previous': paginator.has_previous_page(page - 1),
+            'page': page,
+            'next': page + 1,
+            'previous': page - 1,
+            'pages': paginator.pages,
+            'hits' : paginator.hits,
+        }, self.context_processors)
+        return c
+
+
+# end of file

Added: cs/pythia/trunk/opal/views/View.py
===================================================================
--- cs/pythia/trunk/opal/views/View.py	2007-03-10 01:32:55 UTC (rev 6217)
+++ cs/pythia/trunk/opal/views/View.py	2007-03-10 03:09:03 UTC (rev 6218)
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+#                      California Institute of Technology
+#                        (C) 2007  All Rights Reserved
+#
+# {LicenseText}
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+
+
+class View(object):
+
+
+    def __init__(self, queryset,
+                 template_name=None, template_loader=None,
+                 extra_context=None, context_processors=None,
+                 template_object_name='object',
+                 mimetype=None):
+        self.queryset = queryset
+        if template_name:
+            self.template_name = template_name
+        else:
+            model = queryset.model
+            template_name = "%s/%s_%s.html" % (model._meta.app_label,
+                                               model._meta.object_name.lower(),
+                                               self.templateNameTag)
+        if template_loader is None:
+            from opal.template import loader
+            self.template_loader = loader
+        else:
+            self.template_loader = template_loader
+        if extra_context is None:
+            self.extra_context = {}
+        else:
+            self.extra_context = extra_context
+        self.context_processors = context_processors
+        self.template_object_name = template_object_name
+        self.mimetype = mimetype
+        return
+
+
+    def response(self):
+        raise NotImplementedError("class %r must override 'response'" % self.__class__.__name__)
+
+
+    def loadTemplate(self):
+        return self.template_loader.get_template(self.template_name)
+
+
+    def addExtraContext(self, c):
+        for key, value in self.extra_context.items():
+            if callable(value):
+                c[key] = value()
+            else:
+                c[key] = value
+        return c
+
+
+# end of file

Modified: cs/pythia/trunk/opal/views/__init__.py
===================================================================
--- cs/pythia/trunk/opal/views/__init__.py	2007-03-10 01:32:55 UTC (rev 6217)
+++ cs/pythia/trunk/opal/views/__init__.py	2007-03-10 03:09:03 UTC (rev 6218)
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+#                      California Institute of Technology
+#                        (C) 2007  All Rights Reserved
+#
+# {LicenseText}
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+
+
+from View import View
+from DetailView import DetailView
+from ListView import ListView
+from PaginatedListView import PaginatedListView
+
+
+# end of file

Deleted: cs/pythia/trunk/opal/views/generic/list_detail.py
===================================================================
--- cs/pythia/trunk/opal/views/generic/list_detail.py	2007-03-10 01:32:55 UTC (rev 6217)
+++ cs/pythia/trunk/opal/views/generic/list_detail.py	2007-03-10 03:09:03 UTC (rev 6218)
@@ -1,123 +0,0 @@
-from opal.template import loader, RequestContext
-from opal.http import Http404, HttpResponse
-from opal.core.xheaders import populate_xheaders
-from opal.core.paginator import ObjectPaginator, InvalidPage
-from opal.core.exceptions import ObjectDoesNotExist
-
-def object_list(request, queryset, paginate_by=None, page=None,
-        allow_empty=False, template_name=None, template_loader=loader,
-        extra_context=None, context_processors=None, template_object_name='object',
-        mimetype=None):
-    """
-    Generic list of objects.
-
-    Templates: ``<app_label>/<model_name>_list.html``
-    Context:
-        object_list
-            list of objects
-        is_paginated
-            are the results paginated?
-        results_per_page
-            number of objects per page (if paginated)
-        has_next
-            is there a next page?
-        has_previous
-            is there a prev page?
-        page
-            the current page
-        next
-            the next page
-        previous
-            the previous page
-        pages
-            number of pages, total
-        hits
-            number of objects, total
-    """
-    if extra_context is None: extra_context = {}
-    queryset = queryset._clone()
-    if paginate_by:
-        paginator = ObjectPaginator(queryset, paginate_by)
-        if not page:
-            page = request.GET.get('page', 1)
-        try:
-            page = int(page)
-            object_list = paginator.get_page(page - 1)
-        except (InvalidPage, ValueError):
-            if page == 1 and allow_empty:
-                object_list = []
-            else:
-                raise Http404
-        c = RequestContext(request, {
-            '%s_list' % template_object_name: object_list,
-            'is_paginated': paginator.pages > 1,
-            'results_per_page': paginate_by,
-            'has_next': paginator.has_next_page(page - 1),
-            'has_previous': paginator.has_previous_page(page - 1),
-            'page': page,
-            'next': page + 1,
-            'previous': page - 1,
-            'pages': paginator.pages,
-            'hits' : paginator.hits,
-        }, context_processors)
-    else:
-        c = RequestContext(request, {
-            '%s_list' % template_object_name: queryset,
-            'is_paginated': False
-        }, context_processors)
-        if not allow_empty and len(queryset) == 0:
-            raise Http404
-    for key, value in extra_context.items():
-        if callable(value):
-            c[key] = value()
-        else:
-            c[key] = value
-    if not template_name:
-        model = queryset.model
-        template_name = "%s/%s_list.html" % (model._meta.app_label, model._meta.object_name.lower())
-    t = template_loader.get_template(template_name)
-    return HttpResponse(t.render(c), mimetype=mimetype)
-
-def object_detail(request, queryset, object_id=None, slug=None,
-        slug_field=None, template_name=None, template_name_field=None,
-        template_loader=loader, extra_context=None,
-        context_processors=None, template_object_name='object',
-        mimetype=None):
-    """
-    Generic list of objects.
-
-    Templates: ``<app_label>/<model_name>_detail.html``
-    Context:
-        object
-            the object
-    """
-    if extra_context is None: extra_context = {}
-    model = queryset.model
-    if object_id:
-        queryset = queryset.filter(pk=object_id)
-    elif slug and slug_field:
-        queryset = queryset.filter(**{slug_field: slug})
-    else:
-        raise AttributeError, "Generic detail view must be called with either an object_id or a slug/slug_field."
-    try:
-        obj = queryset.get()
-    except ObjectDoesNotExist:
-        raise Http404, "No %s found matching the query" % (model._meta.verbose_name)
-    if not template_name:
-        template_name = "%s/%s_detail.html" % (model._meta.app_label, model._meta.object_name.lower())
-    if template_name_field:
-        template_name_list = [getattr(obj, template_name_field), template_name]
-        t = template_loader.select_template(template_name_list)
-    else:
-        t = template_loader.get_template(template_name)
-    c = RequestContext(request, {
-        template_object_name: obj,
-    }, context_processors)
-    for key, value in extra_context.items():
-        if callable(value):
-            c[key] = value()
-        else:
-            c[key] = value
-    response = HttpResponse(t.render(c), mimetype=mimetype)
-    populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.name))
-    return response



More information about the cig-commits mailing list