2010-02-22 29 views
16

Supongamos que tengo 3 clases en SQLALchemy: Topic, Tag, Tag_To_Topic.Insertar datos en la relación Muchos a Muchos en SQLAlchemy

¿Es posible escribir algo como:

new_topic = Topic("new topic") 
Topics.tags = ['tag1', 'tag2', 'tag3'] 

que me gustaría para insertar automáticamente 'tag1', 'tag2' y 'etiqueta 3' de la tabla de etiquetas, y también insertar la relación correcta entre new_topic y estas 3 etiquetas en la tabla Tag_To_Topic.

Hasta ahora no he podido averiguar cómo hacerlo debido a la relación de muchos a muchos. (Si fuera uno-a-muchos, sería muy fácil, SQLAlchemy ya lo haría de manera predeterminada. Pero esto es many-to-many.)

¿Esto es posible?

Gracias, Boda Cydo.

Respuesta

15

Puño de todo lo que podría simplificar su relación de muchos a muchos usando association_proxy.

Entonces, me gustaría dejar la relación, ya que es con el fin de no interferir con lo que SA hace:

# here *tag_to_topic* is the relation Table object 
Topic.tags = relation('Tag', secondary=tag_to_topic) 

Y sugiero que acaba de crear una propiedad simple envoltorio que hace el trabajo de la traducción de la cadena lista a los objetos de relación (probablemente cambiarás el nombre de la relación). Sus etiquetas de clase tendría un aspecto similar a:

class Topic(Base): 
    __tablename__ = 'topic' 
    id = Column(Integer, primary_key=True) 
    # ... other properties 

    def _find_or_create_tag(self, tag): 
     q = Tag.query.filter_by(name=tag) 
     t = q.first() 
     if not(t): 
      t = Tag(tag) 
     return t 

    def _get_tags(self): 
     return [x.name for x in self.tags] 

    def _set_tags(self, value): 
     # clear the list first 
     while self.tags: 
      del self.tags[0] 
     # add new tags 
     for tag in value: 
      self.tags.append(self._find_or_create_tag(tag)) 

    str_tags = property(_get_tags, 
         _set_tags, 
         "Property str_tags is a simple wrapper for tags relation") 

A continuación, el código debería funcionar:

# Test 
o = Topic() 
session.add(o) 
session.commit() 
o.str_tags = ['tag1'] 
o.str_tags = ['tag1', 'tag4'] 
session.commit() 
+0

Estoy tratando esto ahora. Enormes gracias por ayudar! – bodacydo

+0

Me gustaría expresar mi profunda gratitud a usted, Van, por ayudarme. Su sugerencia de usar proxy de asociación y mejorar la clase al agregar métodos auxiliares resultó en un gran código y solución. ¡Gracias! – bodacydo

+0

Gracias, van. Pero, ¿cómo "seleccionar" las etiquetas, por ejemplo, para obtener todos los temas que tengan la etiqueta "noticias" y o.year> 2010 (solo una propiedad arbitraria en la instancia de Tema())? –

Cuestiones relacionadas