用SQLAlchemy遍历

这是一个由非专家撰写的存根页。如果你有专业知识,请核实内容,添加食谱,并考虑写一个关于这方面的教程。

root["a"]["b"]

非递归

非递归用例是指某个URL映射到一个表,而下面的组件是一个记录ID。例如:

 1# /persons/123   =>   root["persons"][123]
 2
 3import myapp.model as model
 4
 5class Resource(dict):
 6    def __init__(self, name, parent):
 7        self.__name__ = name
 8        self.__parent__ = parent
 9
10class Root(Resource):
11    """The root resource."""
12
13    def add_resource(self, name, orm_class):
14        self[name] = ORMContainer(name, self, self.request, orm_class)
15
16    def __init__(self, request):
17        self.request = request
18        self.add_resource('persons', model.Person)
19
20root_factory = Root
21
22class ORMContainer(dict):
23    """Traversal component tied to a SQLAlchemy ORM class.
24
25    Calling .__getitem__ fetches a record as an ORM instance, adds certain
26    attributes to the object, and returns it.
27    """
28    def __init__(self, name, parent, request, orm_class):
29        self.__name__  = name
30        self.__parent__ = parent
31        self.request = request
32        self.orm_class = orm_class
33
34    def __getitem__(self, key):
35        try:
36            key = int(key)
37        except ValueError:
38            raise KeyError(key)
39        obj = model.DBSession.query(self.orm_class).get(key)
40        # If the ORM class has a class method '.get' that performs the
41        # query, you could do this:  ``obj = self.orm_class.get(key)``
42        if obj is None:
43            raise KeyError(key)
44        obj.__name__ = key
45        obj.__parent__ = self
46        return obj

在这里, root["persons"] __getitem__ method fetches the specified database record, sets name and parent attribues on it, and returns it. (We've verified that SQLAlchemy does not define __name____parent__ attributes in ORM instances.) If the record is not found, raise KeyError to indicate the resource doesn't exist.

TODO:描述URL生成、访问控制列表以及完整应用程序中需要的其他内容。

这种方法的一个缺点是,为了生成一个指向它的URL,必须获取整个记录。如果索引视图显示到记录的链接,则通过直接查询数据库中符合条件的ID(n个最近记录,所有记录按日期等),这不会有所帮助。您不想获取整个记录的主体,也不想做一些愚蠢的事情,比如在“/persons/123”处向Traversal请求资源,然后生成URL——这将是“/persons/123”!在这种情况下,有几种生成URL的方法:

  • Define a generation-only route; e.g., config.add_route("person", "/persons/{{id}}", static=True)

  • Instead of returning an ORM instance, return a proxy that lazily fetches the instance when its attributes are accessed. This causes traversal to behave somewhat incorrectly. 它 should raise KeyError if the record doesn't exist, but it can't know whether the record exists without fetching it. If traversal returns a possibly-invalid resource, it puts a burden on the view to check whether its context is valid. Normally the view can just assume it is, otherwise the view wouldn't have been invoked.

递归

原型递归用例是一个内容管理系统,用户可以在其中定义任意深度的URL;例如,“/a/b/c”。它还可以用于“屏蔽”数据,在这些数据中,您希望少量的视图响应各种各样的URL层次结构。

Kotti_uu是当前使用Traversal递归地使用sqlAlchemy的最佳示例。Kotti是一个内容管理系统,允许用户定义任意深度的URL。具体来说,Kotti允许用户定义带有子页面的页面,例如页面的“目录”。

科蒂相当复杂,需要一些时间学习。它使用SQLAlchemy的多态性使表从其他表“继承”。这是一个高级功能,可能很复杂。另一方面,如果您有时间,这是学习如何进行递归遍历和多态性的一个很好的方法。

递归SQL设置的主要特征是一个自引用表,即带有外键列的表指向同一个表。这允许每个记录指向其父记录。(根记录在父字段中为空。)