Hello, I'm actually working on an online-game which is already advanced and pretty consequent. As I explained in a previous mail, my goal is to replace the save system actually based on Pickle by SQLAlchemy. If it is possible, it would be better for me to stay with the initial classes organizations and try to map it to the Database without changing anything.
It is a MUD, a textual game. Each player is in a room and each room contains exits leading to other rooms. For example : Player Brian is in a room "kitchen". The room "kitchen" contains an exit "north" leading to the room "bathroom". If player Brian type "north", he leaves the kitchen and goes in the bathroom. Here is my classes organization : Each room contains an instance of the class "Exits". Exits is a class container which contains an OrderedDict always based on the same template : EXIT_NAMES = OrderedDict() EXIT_NAMES["south"] = None EXIT_NAMES["southwest"] = None EXIT_NAMES["west"] = None EXIT_NAMES["northwest"] = None EXIT_NAMES["north"] = None EXIT_NAMES["northeast"] = None EXIT_NAMES["east"] = None EXIT_NAMES["southeast"] = None Initially, everything is setted by None. The room has no exit. When an exit is added, for example at the north of the room, EXIT_NAMES["north"] contains an instance of the class "Exit". Only the values different from None have to be inserted in the Database. I found the following example about the mapping of the OrderedDict in the SQLAlchemy documentation : http://docs.sqlalchemy.org/en/latest/orm/collections.html#custom-dictionary-based-collections I tried to use it and here is what I have done so far : from collections import OrderedDict from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta from sqlalchemy import orm from sqlalchemy.orm import relationship from sqlalchemy import Column, Integer, Boolean, String, ForeignKey from sqlalchemy.orm.collections import attribute_mapped_collection from sqlalchemy.orm.collections import column_mapped_collection from sqlalchemy.util import OrderedDict from sqlalchemy.orm.collections import MappedCollection, collection Base = declarative_base() EXIT_NAMES = OrderedDict() EXIT_NAMES["south"] = None EXIT_NAMES["southwest"] = None EXIT_NAMES["west"] = None EXIT_NAMES["northwest"] = None EXIT_NAMES["north"] = None EXIT_NAMES["northeast"] = None EXIT_NAMES["east"] = None EXIT_NAMES["southheast"] = None class OrderedExits(OrderedDict, MappedCollection): def __init__(self, *args, **kw): MappedCollection.__init__(self, keyfunc=lambda node: node.name) OrderedDict.__init__(self, *args, **kw) class Exits(Base): __tablename__ = "exits_container" id = Column(Integer, primary_key=True) exits = relationship("Exit", collection_class=OrderedExits) def __init__(self): self.exits = OrderedExits(EXIT_NAMES) def __repr__(self): text = "" for s in self.exits.keys(): text = text + s + " : " + str(self.exits [s]) + "\n" return text class Exit(Base): __tablename__ = "exit" id = Column(Integer, primary_key=True) id_sorties = Column(Integer, ForeignKey("exits_container.id"), nullable = False) direction = Column(String) def __init__(self, direction): self.direction = direction def __repr__(self): return self.direction if __name__ == '__main__': engine = create_engine( 'postgresql://USERNAME:PASSWORD@localhost/DATABASE', echo = True) Base.metadata.create_all(engine) Session = sessionmaker(bind=engine) session = Session() south = Exit("south") west = Exit("west") e = Exits() e.exits["south"] = south e.exits["west"] = west session.add(south) session.add(west) session.add(e) session.commit() print(e) Here is the error that I get : Traceback (most recent call last): File "C:\Users\Sven\Desktop\SQL Alchemy Tests\ordereddict.py", line 72, in <module> e = Exits() File "<string>", line 4, in __init__ File "C:\Python34\lib\site-packages\sqlalchemy\orm\state.py", line 415, in _initialize_instance manager.dispatch.init_failure(self, args, kwargs) File "C:\Python34\lib\site-packages\sqlalchemy\util\langhelpers.py", line 66, in __exit__ compat.reraise(exc_type, exc_value, exc_tb) File "C:\Python34\lib\site-packages\sqlalchemy\util\compat.py", line 187, in reraise raise value File "C:\Python34\lib\site-packages\sqlalchemy\orm\state.py", line 412, in _initialize_instance return manager.original_init(*mixed[1:], **kwargs) File "C:\Users\Sven\Desktop\SQL Alchemy Tests\ordereddict.py", line 38, in __init__ self.exits = OrderedExits(EXIT_NAMES) File "C:\Python34\lib\site-packages\sqlalchemy\orm\attributes.py", line 229, in __set__ instance_dict(instance), value, None) File "C:\Python34\lib\site-packages\sqlalchemy\orm\attributes.py", line 1082, in set new_values = list(iterable) File "C:\Python34\lib\site-packages\sqlalchemy\orm\collections.py", line 1535, in _convert new_key = self.keyfunc(value) File "C:\Users\Sven\Desktop\SQL Alchemy Tests\ordereddict.py", line 28, in <lambda> MappedCollection.__init__(self, keyfunc=lambda node: node.name) AttributeError: 'NoneType' object has no attribute 'name' SQLAlchemy doesn't know what to do with the None values, which is logical. How can I say to SQLAlchemy to ignore these values and how can I be sure that SQLAlchemy will be able to populate my objects and set the exits and the None values at the loading of the program ? What is the good way to proceed ? Thank you ! Regards, Sven -- SQLAlchemy - The Python SQL Toolkit and Object Relational Mapper http://www.sqlalchemy.org/ To post example code, please provide an MCVE: Minimal, Complete, and Verifiable Example. See http://stackoverflow.com/help/mcve for a full description. --- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at https://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.