4

我正在按照 mvc 范例设计一个应用程序。我正在使用 sqlalchemy 表达式语言(不是 orm),如果有人好奇,我会使用金字塔。

因此,对于代表系统上的用户的用户类,我有几个访问器方法用于各种数据,例如 avatar_url、name、about 等。我有一个名为 getuser 的方法,它在 db(按名称或 ID),检索用户行,并将其与用户类封装。

但是,我是否必须在每次创建用户类时都进行此查找?如果用户正在查看她的控制面板并想要更改头像并发送 xhr 怎么办;必须创建一个用户对象,并在用户甚至不会使用检索到的数据时查找用户行,这不是一种浪费吗?但只是想对列的子集进行更改?我怀疑这个查找是可以忽略不计的,尽管索引是因为等待 i/o 正确?

更一般地说,必须查询数据库并加载模型类的所有数据以进行任何更改(即使是很小的更改)不是效率低下吗?

我在想我应该只创建一个单独的表单类(因为所做的每个更改都是通过某种表单进行的),并让特定的表单类继承它们,这些 setter 方法将在其中实现。你怎么看?

EX:类:表单 <- 类:Change_password_form <- 功能:change_usr_pass

我真的很感激有关创建适当设计的一些建议;谢谢。

4

2 回答 2

3

SQLAlchemy ORM有一些工具可以简化你的任务。看起来您必须重新发明已经存在于 ORM 层中的一些轮子:“我有一个名为 getuser 的方法,它在 db 中查找用户(按名称或 id),检索用户行,并封装它与用户类” - 这就是 ORM 所做的。

  • 使用 ORM,您有一个 Session,除了其他东西之外,它还用作 ORM 对象的缓存,因此您可以避免在每个事务中多次加载相同的模型。您会发现无论如何都需要加载 User 对象来验证请求,因此根本不查询表可能不是一种选择。

  • 您还可以配置一些属性为延迟加载,这样一些很少需要或笨重的属性只有在您访问它们时才会加载

  • 您还可以将关系配置为在单个查询中快速加载,这可以使您免于执行数百个小的单独查询。我的意思是,在您当前的设计中,以下代码将启动多少个查询:

    for user in get_all_users():
        print user.get_avatar_uri()
        print user.get_name()
        print user.get_about()
    

从您的描述看来,它可能需要 1 + (num_users*3) 次查询。使用 SQLAlchemy ORM,您可以在单个查询中加载所有内容。

结论是:通过主键从数据库中获取单个对象是一种相当便宜的操作,除非您正在构建 facebook 大小的东西,否则您不应该担心这一点。您应该担心的是进行数百个小的单独查询,而一个较大的查询就足够了。这是 SQLAlchemy ORM 非常非常好的领域。

现在,关于“必须创建一个用户对象,并在用户甚至不使用检索到的数据时查找用户行,这难道不是一种浪费;而只是想对列的子集进行更改”-我理解你正在考虑类似的事情

class ChangePasswordForm(...):

    def _change_password(self, user_id, new_password):
         session.execute("UPDATE users ...", user_id, new_password)

    def save(self, request):
         self._change_password(request['user_id'], request['password'])

相对

class ChangePasswordForm(...):

    def save(self, request):
         user = getuser(request['user_id'])
         user.change_password(request['password'])

前一个示例将只发出一个查询,后者必须发出一个 SELECT 并构建用户对象,然后发出一个 UPDATE。后者可能看起来“效率高出两倍”,但在实际应用中,差异可能可以忽略不计。此外,您通常需要从数据库中获取对象,或者进行验证(新密码不能与旧密码相同)、权限检查(用户 Molly 是否允许编辑照片 #12343 的描述?)或记录。

如果您认为执行额外查询的区别很重要(数百万用户不断编辑他们的个人资料图片),那么您可能需要进行一些分析并查看瓶颈在哪里。

于 2012-09-24T00:47:04.327 回答
0

阅读SOLID 原则,在回答您的问题时特别注意S。

创建一个类来执行用户存在检查,并将其注入到任何需要该功能的类中。

另外,还需要创建一个数据持久化类来存储用户的数据,这样就不用每次都查询数据库了。

于 2012-09-23T05:05:14.863 回答