Python:在数据存储中建模一对一关系

发布于 2024-11-28 09:59:12 字数 967 浏览 4 评论 0原文

假设我们有两个模型:UserToken。一个用户可能只有一个Token,一个Token只能属于一个用户。

来自关系数据库,以下似乎是实现方法

class User(db.Model):
    name = db.StringProperty()

class Token(db.Model):
    name = db.StringProperty()
    owner = db.ReferenceProperty(User)

这当然也会创建User.token_set,它是一个db.Query< /代码>。 但我真的很想仅使用 User.token 而不是 User.token_set.get() 来访问令牌,那么怎么样......

class User(db.Model):
    name = db.StringProperty()
    token = db.ReferenceProperty(Token)

class Token(db.Model):
    name = db.StringProperty()
    owner = db.ReferenceProperty(User)

现在我可以以双向方式访问它们:User.token & 用户.所有者。忽略我有那些自动创建的 .token_setuser_set 的事实。

这有什么问题吗?在逻辑方面,在性能方面?

也许我什至不应该有两个模型。实际上,它们都包含四到五个属性。他们应该只是一个吗?什么时候应该放弃一对一关系而将其合并到一个模型中?

感谢您的任何意见!

Let's assume we have two models: User and Token. A user may have only one Token, and a Token can belong to only one user.

Coming from relational databases, the following seems like the way to do it:

class User(db.Model):
    name = db.StringProperty()

class Token(db.Model):
    name = db.StringProperty()
    owner = db.ReferenceProperty(User)

This will of course create User.token_set as well, which is a db.Query.
But I'd really like to access the token with just, say, User.token instead of User.token_set.get(), so how about..

class User(db.Model):
    name = db.StringProperty()
    token = db.ReferenceProperty(Token)

class Token(db.Model):
    name = db.StringProperty()
    owner = db.ReferenceProperty(User)

Now I can access them in a bidirectional fashion: User.token & User.owner. And just ignore the fact that I have those automatically-created .token_set and user_set.

Is there anything wrong with this? On the logic side, on the performance side?

Maybe I shouldn't even have two models. They both, in practice, contain four-five properties. Should they just be one? When's a one-to-one relationship supposed to be ditched in just merged into one model?

Thanks for any input at all!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

将军与妓 2024-12-05 09:59:12

这是 appengine 数据存储。这不是sql。您应该将系统使用的数据分组在一起。假设您有一起使用用户和令牌的地方,并且由于多对一没有问题,因此它们可以放在同一个模型实例中。这将为您提供更好的性能(例如,通过令牌更简单地检索用户)并且更容易处理一致性(更新令牌和用户将在单个事务中进行)。

我不知道这里是否可以接受自链接,所以如果不可以,也许有人会编辑它,但我写了 http://acooke.org/cute/LessonsLea2.html 尝试收集我在数据存储方面的经验。你可能会发现它很有用。

[编辑:思考这个问题的一种方法是:你不是在对数据建模。您正在编写一个旨在扩展的系统。这是驱动一切的因素,而不是建模数据。我并不是说这是一个好主意,但这就是 appengine 所做的。如果您的主要优先事项是建模数据 - 例如,如果您想让多个应用程序以不同的方式使用您的数据 - 那么您不应该使用 appengine。]

this is the appengine data store. it's not sql. you should group together data as it is used by your system. presumably you have places where users and tokens are used together, and since there are no issues with many-to-one these can go in the same model instance. this will give you better performance (much simpler retrieval of user by token, for example) and easier handling of consistency (updating token and user will be within a single transaction).

i don't know if self-linking is acceptable here, so perhaps someone will edit this if not, but i wrote http://acooke.org/cute/LessonsLea2.html to try collect together my experience with the data store. you might find it useful.

[edit: one way to think about this: you're not modeling data. you're writing a system that is intended to scale. that - and not modeling data - is what drives everything. i am not saying this is a good idea, but it's what appengine does. if your main priority is modeling data - for example, if you want to have multiple applications using your data in different ways - then you shouldn't be using appengine.]

dawn曙光 2024-12-05 09:59:12

将 Token 引用添加到用户类有优点也有缺点。作为好处,您将在令牌检索方面获得更好的性能。缺点是插入数据时需要更多事务。

user = User(name='john').put()
token = Token(name='somehash', user=user).put()
user.token = token
user.put()

删除标记时还必须处理空引用。

如果您想要语法糖,也许您可​​以使用类装饰器:

class User(db.Model):
    name = db.StringProperty()

    @property
    def token(self):
        if not hasattr(self, '_token_cached'):
            setattr(self, '_token_cached', self.token_set.get())
       return self._token_cached

Adding Token reference to user class has pros and cons. As benefit you will have better performance in token retrieval. As cons you will need more transactions when inserting data.

user = User(name='john').put()
token = Token(name='somehash', user=user).put()
user.token = token
user.put()

You also have to deal with null references when deleting tokens.

Perhaps you can go with class decorators if syntax sugar is what you want:

class User(db.Model):
    name = db.StringProperty()

    @property
    def token(self):
        if not hasattr(self, '_token_cached'):
            setattr(self, '_token_cached', self.token_set.get())
       return self._token_cached
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文