Django ORM:缓存和操作ForeignKey对象 [英] Django ORM: caching and manipulating ForeignKey objects

查看:143
本文介绍了Django ORM:缓存和操作ForeignKey对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下用于空间征服游戏的models.py的骨架:

Consider the following skeleton of a models.py for a space conquest game:

class Fleet(models.Model):
    game = models.ForeignKey(Game, related_name='planet_set')
    owner = models.ForeignKey(User, related_name='planet_set', null=True, blank=True)
    home = models.ForeignKey(Planet, related_name='departing_fleet_set')
    dest = models.ForeignKey(Planet, related_name='arriving_fleet_set')
    ships = models.IntegerField()

class Planet(models.Model):
    game = models.ForeignKey(Game, related_name='planet_set')
    owner = models.ForeignKey(User, related_name='planet_set', null=True, blank=True)
    name = models.CharField(max_length=250)
    ships = models.IntegerField()

对于我正在开展的项目,我有很多这样的数据模型,我根据各种数据对象之间的一些复杂的交互来改变游戏的状态。我想避免对数据库进行大量的不必要的调用,所以每转一次,我做一些类似

I have many such data models for a project I'm working on, and I change the state of the game based on somewhat complicated interactions between various data objects. I want to avoid lots of unnecessary calls to the database, so once per turn, I do something like

  1. 查询所有的队列,行星和其他对象数据库并将其缓存为python对象

  2. 处理游戏对象,解决游戏状态

  3. 将它们保存回数据库

当使用ForeignKey对象时,此模型似乎完全崩溃。例如,当一个新的舰队离开地球时,我有一条看起来像这样的线条:

This model seems to totally break down when using ForeignKey objects. For example, when a new fleet departs a planet, I have a line that looks something like this:

fleet.home.ships -= fleet.ships

在此行运行后,我有其他代码更改船舶数量每个行星,包括行星舰队。不幸的是,上面提到的变化没有反映在我之前获得的行星的查询集中,所以当我在转弯结束时保存所有行星时,对fleet.home的船只的改变将被覆盖。

After this line runs, I have other code that alters the number of ships at each of the planets, including the planet fleet.home. Unfortunately, the changes made in the above line are not reflected in the QuerySet of planets that I obtained earlier, so that when I save all the planets at the end of the turn, the changes to fleet.home's ships get overwritten.

有没有更好的处理这种情况的方法?或者这就是所有ORM是如何的?

Is there some better way of handling this situation? Or is this just how all ORMs are?

推荐答案

Django的ORM不实现身份图(它位于售票追踪器,但不清楚是否或何时实现;至少有一个核心Django提交者具有表示反对它)。这意味着如果您通过两个不同的查询路径到达同一个数据库对象,那么您正在使用内存中的不同Python对象。

Django's ORM does not implement an identity map (it's in the ticket tracker, but it isn't clear if or when it will be implemented; at least one core Django committer has expressed opposition to it). This means that if you arrive at the same database object through two different query paths, you are working with different Python objects in memory.

这意味着您的设计(加载所有内容一次进入内存,修改很多东西,然后将其全部保存回来)使用Django ORM不可行。首先,因为它会经常浪费大量内存加载在同一个对象的副本中,其次是因为覆盖问题,如你所遇到的问题。

This means that your design (load everything into memory at once, modify a lot of things, then save it all back at the end) is unworkable using the Django ORM. First because it will often waste lots of memory loading in duplicate copies of the same object, and second because of "overwriting" issues like the one you're running into.

您需要重新设计您的设计以避免这些问题(请谨慎操作,一次只能使用一个QuerySet,在进行其他查询之前保存任何修改;或者,如果加载多个查询,请手动查找所有关系,不要使用它们的便捷属性遍历ForeignKeys),或者使用实现身份映射的替代Python ORM。 SQLAlchemy 是一个选项。

You either need to rework your design to avoid these issues (either be careful to work with only one QuerySet at a time, saving anything modified before you make another query; or if you load several queries, look up all relations manually, don't ever traverse ForeignKeys using the convenient attributes for them), or use an alternative Python ORM that implements identity map. SQLAlchemy is one option.

请注意,这不意思是Django的ORM是坏。它针对Web应用程序进行了优化,这些问题很少见(几年来我已经用Django进行Web开发,从来没有在真正的项目中遇到这个问题)。如果您的用例不同,您可能需要选择其他ORM。

Note that this doesn't mean Django's ORM is "bad." It's optimized for the case of web applications, where these kinds of issues are rare (I've done web development with Django for years and never once had this problem on a real project). If your use case is different, you may want to choose a different ORM.

这篇关于Django ORM:缓存和操作ForeignKey对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆