It looks ok to me, at least to the extent that I don't know if there one way of 
implementing __getitem__ is better than any other for purposes of traversal, 
as long as it returns the right answer.

- C

Nikos Papagrigoriou wrote:
> Hi everyone,
> 
> I used the bfg_alchemy paster template to create a default project  
> with Traversal and SQLAlchemy. This gave me an initial insight on how  
> to use traversal with an ORM and support URLs like 
> http://example.com/projects/{project_id}.
> 
> In order to support something like:
> 
>   - http://example.com/tasks (all the tasks)
>   - http://example.com/projects/{project_id}/tasks (all the tasks by  
> project)
>   - http://example.com/projects/{project_id}/tasks/{task_id}
> 
> where projects/tasks are collections of resources and {projects_id}/ 
> {task_id} represents one particular project resource, I came up with  
> the following idea:
> 
>   - Create SQLAlchemy aware containers that expect a DBSession and  
> "filter_by" keyword arguments.
>   - Adapt the contained items when there are subordinate containers.
> 
> Of course I could just make a contained item (e.g. a project resource)  
> traversable and avoid the adaption but I wanted to keep the individual  
> resources unaware from the fact that the current application framework  
> supports traversal (which I actually like a lot :-) ). Besides with  
> adaption the subordinate contents of one resource may vary based on  
> the parent container.
> 
> I am enclosing part of the code but you can download an experimental  
> application from http://dl.getdropbox.com/u/260650/bfg_alchemy.zip  
> (temporary location)
> 
> Do you think my approach makes sense or is it too complicated?
> 
> Cheers,
> 
> Nikos.
> 
> ---------------------------------- example code  
> ----------------------------------
> 
> class TraversableMapping(Contained):
>      implements(ITraversable)
> 
>      title = u''
>      description = u''
> 
>      def __init__(self):
>          self._contents = self._create_contents()
>          for name in self._contents:
>              locate(self._contents[name], self, name)
> 
>      def __getitem__(self, key):
>          return self._contents[key]
> 
>      def get(self, key, default=None):
>          return self._contents.get(key, default)
> 
>      def items(self):
>          return self._contents.items()
> 
>      def iteritems(self):
>          return self._contents.iteritems()
> 
>      def values(self):
>          return self._contents.values()
> 
>      def itervalues(self):
>          return self._contents.itervalues()
> 
>      def __len__(self):
>          return len(self._contents)
> 
>      def _create_contents(self):
>          raise NotImplementedError
> 
> 
> class TraversableEntity(Contained):
>      implements(ITraversable)
> 
>      _entity = None
> 
>      def __init__(self, db_session, **filters):
>          self.__db_session = db_session
>          self.__filters = filters
> 
>      def __getitem__(self, key):
>          try:
>              key = int(key)
>          except (ValueError, TypeError):
>              raise KeyError(key)
>          query = self._query.filter_by(id=key)
>          try:
>              item = query.one()
>          except NoResultFound:
>              raise KeyError(key)
>          else:
>              item = queryMultiAdapter((self, item), default=item)
>              locate(item, self, key)
>              return item
> 
>      def __len__(self):
>          return self._query.count()
> 
>      def get(self, key, default=None):
>          try:
>              item = self.__getitem__(key)
>          except KeyError:
>              item = default
>          return item
> 
>      def items(self):
>          result = []
>          for obj in self._query.all():
>              locate(obj, self, obj.id)
>              result.append((obj.id, obj))
>          return result
> 
>      def iteritems(self):
>          for obj in self._query:
>              locate(obj, self, obj.id)
>              yield (obj.id, obj)
> 
>      def values(self):
>          result = []
>          for obj in self._query.all():
>              locate(obj, self, obj.id)
>              result.append(obj)
>          return result
> 
>      def itervalues(self):
>          for obj in self._query:
>              locate(obj, self, obj.id)
>              yield obj
> 
>      @property
>      def _query(self):
>          session = self.__db_session()
>          query = session.query(self._entity)
>          if len(self.__filters) > 0:
>              query = query.filter_by(**self.__filters)
>          return query
> 
> 
> class TraversableProject(TraversableMapping):
>      implements(IProject)
>      adapts(IProjectContainer, IProject)
> 
>      def __init__(self, parent, child):
>          self._parent = parent
>          self._child = child
>          self.title = self._child.title
>          self.description = self._child.description
>          TraversableMapping.__init__(self)
> 
>      def __getattr__(self, name):
>          return getattr(self._child, name)
> 
>      def _create_contents(self):
>          return dict(tasks=TaskContainer(DBSession,  
> project_id=self._child.id))
> 
> 
> class ProjectContainer(TraversableEntity):
>      implements(IProjectContainer)
> 
>      title = u'Projects'
>      description = u'List of projects'
>      _entity = Project
> 
> _______________________________________________
> Repoze-dev mailing list
> Repoze-dev@lists.repoze.org
> http://lists.repoze.org/listinfo/repoze-dev
> 

_______________________________________________
Repoze-dev mailing list
Repoze-dev@lists.repoze.org
http://lists.repoze.org/listinfo/repoze-dev

Reply via email to