SQLAlchemy与Pyramid,如何在上下文外获取资源?

5 投票
1 回答
1449 浏览
提问于 2025-04-17 07:57

我在理解我的Pyramid网页应用时遇到了一些问题。我的应用结构和Michael Merickel在这里描述的很相似,不过我使用的是纯遍历来找到我的视图(这些视图是用context='path.toResource'和name='myView'来配置的),这在我看来是比较标准的做法,具体可以参考遍历的维基教程。不过,我的应用有一个更复杂的URL结构:我的用户资源在/users/{user_id}下,而我的项目在/projects/{project_id}下。所有的资源都是通过SQLAlchemy ORM来持久化的;我有一个用户类和一个项目类,它们都有__name____parent__属性,还有其他一些扩展了Columns的属性。

class User(Base):
    id = Column(...)
    __name__ = None
    __parent__ = None
Class Project(Base):
    id = Column(...)
    __name__ = None
    __parent__ = None
    owner_id = Column(...ForeignKey(User.id))
    owner = relationship(User,...)

我有一个RootFactory、ProjectFactory和UserFactory,它们在__get_item__调用中填充了相应的__name____parent__属性。

所以,在项目上下文的视图函数中,我可以在request.context中获取到一个项目实例。我的问题是,我该如何引用对应的用户实例呢?我不能直接用project.owner,因为那个用户实例没有经过RootFactory的链条,所以它的__parent____name__值没有设置。这很糟糕,因为我想用request.resource_url来找到拥有者用户的URL,这样我就可以在视图页面上放一个链接。

这里的解决方案是什么呢,SO?我是不是应该通过request.root来做所有的事情?如果我想做一个复杂的查询,返回用户或项目实例,该怎么办?有没有什么“CrapFactory”可以传给SQLAlchemy,这样它的所有实例都能正确填充?

我的方法是不是完全错了?

我感觉如果我只坚持使用URL路由,就不会遇到这些问题了……

1 个回答

5

这是大家在尝试把SQLAlchemy和遍历功能结合时常遇到的问题。遍历的一个要求是要有一个持久的树形结构,这样你才能从一个节点跳到另一个节点。

基本上,你有两个选择。

  1. 你可以在数据库中真正建立一棵树,每个资源都知道自己在树中的位置。这样,当你加载一个资源时,它就能找到自己的父节点和名称。这是最好的选择。通常的做法是创建一个自引用的资源表。然后你的UserProject对象都会有resource_id这个外键,用来确定它们在树中的位置。

  2. 目前你的名称和父节点只有在从根节点遍历树时才会被填充,所以你可以通过request.root来引用树的其他部分。

你也可以在每个资源上定义一个__resource_url__属性,但这在大多数情况下都比较“黑科技”,不太推荐。

需要注意的是,单纯说“我的网址有这个结构”和实际构建一个可以使用的持久层级结构是有很大区别的。处理网址相对简单,但如果没有持久的树来生成它们,就会变得很麻烦。

撰写回答