[Python] SQLAlchemy, liste contenant plusieurs types

SQLAlchemy, liste contenant plusieurs types [Python] - Python - Programmation

Marsh Posté le 01-08-2008 à 13:59:32    

Bonjour, je découvre SQLAlchemy a travers Turbogears et je suis devant un petit problème.
 
Je veux créer un modèle de galaxie à travers trois classes différentes (au final il doit y en avoir beaucoup plus) :

  • System()
  • Star()
  • Planet()


Chacunes de ces classes possède un attribut children qui est une liste contenant tout les objects qui lui sont attachés.  
Typiquement on aurait System -> Star -> Planet. Jusque là pas de problème.
Là où le problème se pose c'est si je veux que l'attribut children puisse contenir plusieurs classes, exemple:
Imaginons un systeme contenant une étoile avec ses planètes, mais également une planète qui n'est pas dans l'orbite de l'étoile
System -> Star -> Planet
           -> Planet
 
Voici le code que j'ai écris pour faire face à ce cas :

Code :
  1. # your data tables
  2. systems_table = Table('systems', metadata,
  3.                       Column('ID', Unicode, primary_key=True)
  4.                       )
  5. stars_table = Table('stars', metadata,
  6.                     Column('ID', Unicode, primary_key=True),
  7.                     Column('parent_id', Unicode, ForeignKey('systems.ID'))
  8.                     )
  9. planets_table = Table('planets', metadata,
  10.                       Column('ID', Unicode, primary_key=True),
  11.                       Column('parent_id', Unicode, ForeignKey('stars.ID'),
  12.                                                    ForeignKey('systems.ID'))
  13.                       )
  14. # your model classes
  15. class System(object):
  16.     pass
  17. class Star(object):
  18.     pass
  19. class Planet(object):
  20.     pass
  21. # set up mappers between your data tables and classes
  22. mapper(System, systems_table, properties={'children':relation(Star),
  23.                                                             'children':relation(Planet)})
  24. mapper(Star, stars_table, properties={'children':relation(Planet)})
  25. mapper(Planet, planets_table)


 
Tout va bien jusqu'a ce que je commit les changements:
 


>>> mysys = System()
>>> mystar = Star()
>>> myplanet = Planet()
>>> mysys.ID = 1
>>> mystar.ID = 2
>>> myplanet.ID = 3
>>> mylostplanet = Planet()
>>> mylostplanet.ID = 4
>>> mysys.children.append(mystar)
>>> mysys.children.append(mylostplanet)
>>> mystar.children.append(myplanet)
>>> session.flush()
...
...
...
FlushError: Attempting to flush an item of type <class 'x4m.model.Planet'> on co
llection 'System.children', whose mapper does not inherit from that of <class 'x
4m.model.Star'>.


 
Je m'en remets à vous. :)

Reply

Marsh Posté le 01-08-2008 à 13:59:32   

Reply

Marsh Posté le 01-08-2008 à 15:38:03    

Ouais, mais nan :o
 
Je sais plus ce que fais SQLAlchemy exactement pour les propriétés, mais vu que tu défini deux fois la même propriété 'children' (dans ton mapper sur la classe System), y'en a un qui écrase l'autre.
Vu le message d'erreur, on dirait qu'il garde que la relation avec Star.
 
 
Ceci dit, c'est pas vraiment un problème lié à SQLAlchemy, mais plutôt un problème de conception : ton System contient des objets, qui sont soit des Stars, soit des Planets. Et une Star contient des Planets.
 
Donc, il faut que tu généralises le concept d'objets d'un système, qui sera soit une Star, soit une Planet, et ton System contiendra ce genre d'objets.
Regarde comment faire de l'héritage avec SQLAlchemy.

Reply

Marsh Posté le 01-08-2008 à 15:41:57    

Un truc du genre (pseudo langage)

Code :
  1. class System:
  2.    children : SystemObject list
  3.  
  4. class SystemObject(abstract):
  5.    pass
  6.  
  7. class Star(SystemObject):
  8.    children : Planet list
  9.  
  10. class Planet(SystemObject):
  11.    pass


SystemObject est une classe "abstraite", juste là pour représenter la relation de parenté entre Star et Planet.

Reply

Marsh Posté le 02-08-2008 à 13:18:08    

Merci beaucoup, c'est exactement ça.
Pour ceux que cela intéressent voici mon code:

Code :
  1. # your data tables
  2.  
  3. spatialobjects_table = Table('spatialobjects', metadata,
  4.                            Column('unique_ID', Unicode, primary_key=True),
  5.                            Column('name', Unicode),
  6.                            Column('children_id', Unicode, ForeignKey('spatialobjects.unique_ID')),
  7.                            Column('type', Unicode, nullable=False)
  8.                            )
  9. systems_table = Table('systems', metadata,
  10.                      Column('unique_ID', Unicode, ForeignKey('spatialobjects.unique_ID'), primary_key=True)
  11.                      )
  12. stars_table = Table('stars', metadata,
  13.                    Column('unique_ID', Unicode, ForeignKey('spatialobjects.unique_ID'), primary_key=True)
  14.                    )
  15. planets_table = Table('planets', metadata,
  16.                      Column('unique_ID', Unicode, ForeignKey('spatialobjects.unique_ID'), primary_key=True)
  17.                      )
  18. # your model classes
  19.  
  20. class SpatialObject(object):
  21.    pass
  22.  
  23. class System(SpatialObject):
  24.    pass
  25.  
  26. class Star(SpatialObject):
  27.    pass
  28.  
  29. class Planet(SpatialObject):
  30.    pass
  31.  
  32. # set up mappers between your data tables and classes
  33. mapper(SpatialObject, spatialobjects_table, polymorphic_on=spatialobjects_table.c.type, polymorphic_identity='spatialobject', properties={'children':relation(SpatialObject, backref=backref('parent', remote_side=[spatialobjects_table.c.unique_ID]))})
  34. mapper(System, systems_table, inherits=SpatialObject, polymorphic_identity='system')
  35. mapper(Star, stars_table, inherits=SpatialObject, polymorphic_identity='star')
  36. mapper(Planet, planets_table, inherits=SpatialObject, polymorphic_identity='planet')
 

Si System hérite aussi de SpatialObject c'est parcque un systeme de deux planètes peut exister dans l'orbite d'une etoile et donc dans un autre systeme plus grand. :)


Message édité par alien conspiracy le 02-08-2008 à 13:25:54
Reply

Marsh Posté le 08-10-2008 à 09:28:28    

salut!
j'ai vue ton mail et je voudrais savoir si sqlalchemy est une base de donnée puissant car je veux utiliser un bd avec python et je cherche un truc commme mysql, merci pour ton aide

Reply

Marsh Posté le 08-10-2008 à 09:45:31    

falifalibe a écrit :

sqlalchemy est une base de donnée


non :o


---------------
Nos estans firs di nosse pitite patreye...
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed