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