2009-04-23 16 views
15

Tengo una pregunta sobre el SQLAlchemy. ¿Cómo puedo agregar a mi clase asignada el atributo tipo diccionario, que mapea las claves de cadena en valores de cadena y que se almacenarán en la base de datos (en la misma u otra tabla como objeto mapeado original). Quiero que esto agregue soporte para etiquetas arbitrarias de mis objetos.SQLAlchemy - Diccionario de etiquetas

he encontrado el siguiente ejemplo en la documentación SQLAlchemy:

from sqlalchemy.orm.collections import column_mapped_collection, attribute_mapped_collection, mapped_collection 

mapper(Item, items_table, properties={ 
# key by column 
'notes': relation(Note, collection_class=column_mapped_collection(notes_table.c.keyword)), 
# or named attribute 
'notes2': relation(Note, collection_class=attribute_mapped_collection('keyword')), 
# or any callable 
'notes3': relation(Note, collection_class=mapped_collection(lambda entity: entity.a + entity.b)) 
}) 

item = Item() 
item.notes['color'] = Note('color', 'blue') 

pero quiero que el siguiente comportamiento:

mapper(Item, items_table, properties={ 
# key by column 
'notes': relation(...), 
}) 

item = Item() 
item.notes['color'] = 'blue' 

Es posible en SQLAlchemy?

Gracias

Respuesta

21

La respuesta simple es .

Sólo tiene que utilizar un proxy de asociación:

from sqlalchemy import Column, Integer, String, Table, create_engine 
from sqlalchemy import orm, MetaData, Column, ForeignKey 
from sqlalchemy.orm import relation, mapper, sessionmaker 
from sqlalchemy.orm.collections import column_mapped_collection 
from sqlalchemy.ext.associationproxy import association_proxy 

Crear un entorno de prueba:

engine = create_engine('sqlite:///:memory:', echo=True) 
meta = MetaData(bind=engine) 

definir las tablas:

tb_items = Table('items', meta, 
     Column('id', Integer, primary_key=True), 
     Column('name', String(20)), 
     Column('description', String(100)), 
    ) 
tb_notes = Table('notes', meta, 
     Column('id_item', Integer, ForeignKey('items.id'), primary_key=True), 
     Column('name', String(20), primary_key=True), 
     Column('value', String(100)), 
    ) 
meta.create_all() 

clases (tenga en cuenta el association_proxy en la clase):

class Note(object): 
    def __init__(self, name, value): 
     self.name = name 
     self.value = value 
class Item(object): 
    def __init__(self, name, description=''): 
     self.name = name 
     self.description = description 
    notes = association_proxy('_notesdict', 'value', creator=Note) 

Mapping:

mapper(Note, tb_notes) 
mapper(Item, tb_items, properties={ 
     '_notesdict': relation(Note, 
      collection_class=column_mapped_collection(tb_notes.c.name)), 
    }) 

A continuación, sólo probarlo:

Session = sessionmaker(bind=engine) 
s = Session() 

i = Item('ball', 'A round full ball') 
i.notes['color'] = 'orange' 
i.notes['size'] = 'big' 
i.notes['data'] = 'none' 

s.add(i) 
s.commit() 
print i.notes 

que imprime:

{u'color': u'orange', u'data': u'none', u'size': u'big'} 

Pero, son los de la tabla notas?

>>> print list(tb_notes.select().execute()) 
[(1, u'color', u'orange'), (1, u'data', u'none'), (1, u'size', u'big')] 

¡Funciona! :)

+0

¿Cómo se puede eliminar 'i', entonces?Obtengo un 'aise AssertionError ("La regla de dependencia intentó anular la columna de la clave principal'% s 'en la instancia'% s '"% (r, mapperutil.state_str (dest))) excepción al intentar 's.delete (i) ' – Sardathrion

+0

Respondiendo a mi propia pregunta:' En mapper (elemento [...], cascade = "all, delete-huérfano"), [...] ' – Sardathrion

-6

La respuesta simple es 'no'.

SQLAlchemy es un contenedor en una base de datos SQL.

Los ejemplos de relaciones que citas traducen una relación entre tablas SQL en una estructura similar a un mapa de Python para simplificar un poco las instrucciones SQL SELECT y ubicar filas en otra tabla.

El

item.notes['color'] = Note('color', 'blue') 

es esencial porque el Note es una tabla separada con dos columnas. No puede dejar la parte Note.

Debe definir esta otra tabla SQL y debe crear objetos que estén asignados a esa tabla SQL.