当前位置: 首页 > 面试题库 >

SQLAlchemy提交对通过__dict__修改的对象的更改

吕修筠
2023-03-14
问题内容

我正在开发一个多人游戏。当我使用清单中的对象时,它应使用对象的属性值更新用户生物的统计信息。

这是我的代码:

try:
    obj = self._get_obj_by_id(self.query['ObjectID']).first()

    # Get user's current creature
    cur_creature = self.user.get_current_creature()

    # Applying object attributes to user attributes
    for attribute in obj.attributes:
        cur_creature.__dict__[str(attribute.Name)] += attribute.Value

    dbObjs.session.commit()
except (KeyError, AttributeError) as err:
    self.query_failed(err)

现在,由于某种原因,这不能正确地执行操作,因此我尝试了:

cur_creature.Health  = 100
logging.warning(cur_creature.Health)
dbObjs.session.commit()

哪个可行,但不是很方便(因为我需要一个大的if语句来更新该生物的不同统计信息)

所以我尝试了:

cur_creature.__dict__['Health'] = 100
logging.warning(cur_creature.Health)
dbObjs.session.commit()

我进入100日志,但是没有任何更改,所以我尝试了:

cur_creature.__dict__['Health'] = 100
cur_creature.Health  = cur_creature.__dict__['Health']
logging.warning(cur_creature.Health)
dbObjs.session.commit()

日志中仍然为“ 100”,但没有更改,因此我尝试:

cur_creature.__dict__['Health'] = 100
cur_creature.Health  = 100
logging.warning(cur_creature.Health)
dbObjs.session.commit()

仍然会在日志中写入100,但不会将更改提交到数据库。现在,这很奇怪,因为仅在工作版本方面有所不同,因为它的最上面是这一行:

cur_creature.__dict__['Health'] = 100

摘要: 如果我直接修改属性,则提交工作正常。相反,如果我通过类的字典修改属性,则无论以后如何修改它,都不会将更改提交到数据库。

有任何想法吗?

提前致谢

更新1:

另外,这将更新数据库中的“健康”,但不会更新“饥饿”:

cur_creature.__dict__['Hunger'] = 0
cur_creature.Health  = 100
cur_creature.Hunger = 0
logging.warning(cur_creature.Health)
dbObjs.session.commit()

因此,一般来说,访问字典对于属性来说不是问题,但是通过字典修改属性可以防止对该属性的更改被提交。

更新2:

作为临时解决方案,我覆盖__set_item__(self)了该类中的函数Creatures

def __setitem__(self, key, value):
    if key == "Health":
       self.Health = value
    elif key == "Hunger":
       self.Hunger = value

这样,“使用对象”的新代码为:

try:
    obj = self._get_obj_by_id(self.query['ObjectID']).first()

    # Get user's current creature
    cur_creature = self.user.get_current_creature()

    # Applying object attributes to user attributes
    for attribute in obj.attributes:
        cur_creature[str(attribute.Name)] += attribute.Value

    dbObjs.session.commit()
except (KeyError, AttributeError) as err:
    self.query_failed(err)

更新3:

通过查看答案中的建议,我选择了以下解决方案:

Creatures

def __setitem__(self, key, value):
    if key in self.__dict__:
       setattr(self, key, value)
    else:
       raise KeyError(key)

在另一种方法

 # Applying object attributes to user attributes
 for attribute in obj.attributes:
     cur_creature[str(attribute.Name)] += attribute.Value

问题答案:

问题不在于SQLAlchemy,而是由于Python的描述符机制。每个Column属性都是一个描述符:这就是SQLAlchemy如何“挂钩”属性检索和修改以产生数据库请求。

让我们尝试一个简单的例子:

class Desc(object):
    def __get__(self, obj, type=None):
        print '__get__'
    def __set__(self, obj, value):
        print '__set__'

class A(object):
    desc = Desc()

a = A()
a.desc                  # prints '__get__'
a.desc = 2              # prints '__set__'

但是,如果浏览a 实例
字典并为设置另一个值'desc',则会绕过描述符协议(请参阅调用描述符):

a.__dict__['desc'] = 0  # Does not print anything !

在这里,我们只是创建了一个名为0的新 实例
属性'desc'。该Desc.__set__方法从未被调用过,在您的情况下,SQLAlchemy不会获得“捕获”分配的机会。

解决的办法是使用setattr,这完全等同于编写a.desc

setattr(a, 'desc', 1)   # Prints '__set__'


 类似资料:
  • 本文向大家介绍python实现通过shelve修改对象实例,包括了python实现通过shelve修改对象实例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了python实现通过shelve修改对象的方法,分享给大家供大家参考。 具体实现方法如下: 本文实例测试环境为Python2.7.6 程序运行结果如下: 实例代码及运行结果均配有较为详尽的注释,帮助大家理解其含义。希望本文所述对大家的

  • 问题内容: 我要复制到 是一组对象。我正在根据某些条件进行修改。问题是,如果我修改,它也会被修改。 问题答案: 显然,您对声明的功能有一些误解。 在JavaScript中,对象是通过引用传递和分配的(更准确地说是引用的值),所以和都是对同一对象的引用。 这是一个简化的插图,可以帮助您可视化正在发生的事情 如您在分配后所看到的,两个引用都指向同一对象。 如果需要修改一个而不是另一个,则需要 创建一个

  • 我一直在研究猫鼬文档,但我找不到一种方法来实现我想要做的事情。考虑一个MangGDB用户集合。还可以考虑一个包含DB集合中所有字段的蒙古人用户模式。 现在,我想登录到控制台,所有用户,但属性已更改。有点像: 用户。图例(): 给定的异步类型。find()函数我不确定这是否可以实现。我来自C#和PHP背景,只处理关系数据库,这可以通过在用户类中使用只返回所需值的函数轻松实现。 能做到吗?!

  • 你可以使用点号(.)来修改 JSON 对象的值。如: myObj.zhihu = "https://www.zhihu.com/people/leiqikui/"; 你可以使用中括号([])来修改 JSON 对象的值。如: myObj["zhihu"] = "https://www.zhihu.com/people/leiqikui/";

  • 指定amend选项执行提交的话,可以修改同一个分支最近的提交内容和注解。 主要使用的场合: 添加最近提交时漏掉的档案 修改最近提交的注解

  • 若要把文件或目录的添加和变更保存到数据库,就需要进行提交。 执行提交后,数据库中会生成上次提交的状态与当前状态的差异记录(也被称为revision)。 如下图,提交是以时间顺序排列状态被保存到数据库中的。凭借该提交和最新的文件状态,就可以知道过去的修改记录以及内容。 系统会根据修改的内容计算出没有重复的40位英文及数字来给提交命名。指定这个命名,就可以在数据库中找到对应的提交。 Tips(小贴士