Note that there are some explanatory texts on larger screens.

plurals
  1. POSQLAlchemy commit changes to object modified through __dict__
    text
    copied!<p>I am developing a multiplayer game. When I use an object from inventory, it should update the user creature's stats with the values of the attributes of an object. </p> <p>This is my code:</p> <pre><code>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) </code></pre> <p>Now, this doesn't commit things properly for some reason, so I tried:</p> <pre><code>cur_creature.Health = 100 logging.warning(cur_creature.Health) dbObjs.session.commit() </code></pre> <p>Which works, but is not very convenient (since I would need a big if statement to updated the different stats of the creature)</p> <p>So I tried:</p> <pre><code>cur_creature.__dict__['Health'] = 100 logging.warning(cur_creature.Health) dbObjs.session.commit() </code></pre> <p>I get <code>100</code> in logs, but no changes, so I tried:</p> <pre><code>cur_creature.__dict__['Health'] = 100 cur_creature.Health = cur_creature.__dict__['Health'] logging.warning(cur_creature.Health) dbObjs.session.commit() </code></pre> <p>Still '100' in logs, but no changes, so I tried:</p> <pre><code>cur_creature.__dict__['Health'] = 100 cur_creature.Health = 100 logging.warning(cur_creature.Health) dbObjs.session.commit() </code></pre> <p>Which still writes 100 in the logs, but doesn't commit changes to the database. Now, this is weird, since it only differ by the working version for the fact that it has this line on top:</p> <pre><code>cur_creature.__dict__['Health'] = 100 </code></pre> <p><strong>Summary:</strong> If I modify an attribute directly, commit works fine. Instead, if I modify an attribute through the class' dictionary, then, no matter how I modify it afterwards, it doesn't commit changes to the db.</p> <p>Any ideas?</p> <p>Thanks in advance</p> <p>UPDATE 1:</p> <p>Also, this updates Health in the db, but not Hunger:</p> <pre><code>cur_creature.__dict__['Hunger'] = 0 cur_creature.Health = 100 cur_creature.Hunger = 0 logging.warning(cur_creature.Health) dbObjs.session.commit() </code></pre> <p>So just accessing the dictionary is not a problem for attributes in general, but modifying an attribute through the dictionary, prevents the changes to that attributes from being committed.</p> <p>Update 2:</p> <p>As a temporary fix, I've overridden the function <code>__set_item__(self)</code> in the class <code>Creatures</code>:</p> <pre><code>def __setitem__(self, key, value): if key == "Health": self.Health = value elif key == "Hunger": self.Hunger = value </code></pre> <p>So that the new code for 'use object' is:</p> <pre><code>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) </code></pre> <p>Update 3: </p> <p>By having a look at the suggestions in the answers, I settled down for this solution:</p> <p>In <code>Creatures</code></p> <pre><code>def __setitem__(self, key, value): if key in self.__dict__: setattr(self, key, value) else: raise KeyError(key) </code></pre> <p>In the other method</p> <pre><code> # Applying object attributes to user attributes for attribute in obj.attributes: cur_creature[str(attribute.Name)] += attribute.Value </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload