remove query many init_app delete binds python sqlalchemy metaclass

python - many - sqlalchemy query



Metaclass personalizado para crear propiedades híbridas en SQLAlchemy (1)

No es necesario utilizar metaclases para una clase mapeada SQLAlchemy ya que suministramos muchos eventos para agregar características a las clases a medida que se crean y / o mapean. mapper_configured podría ser bueno aquí, que si tienes 0.8 puedes aplicar a MyBase directamente:

@event.listens_for(MyBase, ''mapper_configured'') def get_special_columns(mapper, cls): for attrname in dir(cls): val = getattr(cls, attrname) if isinstance(val, SpecialColumn): name1, name2 = "_%s_1" % attrname, "_%s_2" % attrname setattr(cls, name1, Column(...)) setattr(cls, name2, Column(...)) @hybrid_property def myhybrid(self): return getattr(self, name1), getattr(self, name2) @myhybrid.setter def myhybrid(self, value): setattr(self, name1, value[0]) setattr(self, name2, value[1]) setattr(cls, attrname, myhybrid)

tenga en cuenta que setattr () es la mejor manera de ir aquí, simple y al grano.

Quiero crear una interfaz personalizada sobre SQLAlchemy para que algunas propiedades híbridas predefinidas sean compatibles de forma transparente.

Específicamente, quiero crear una clase SpecialColumn y una metaclase para que cuando un usuario agregue SpecialColumn como un atributo de una clase, mi metaclass personalizada reemplace ese atributo con dos SQLAlchemy Column y agregue una propiedad híbrida que obtenga y establezca esas dos columnas como una tupla Aquí está mi enfoque hasta ahora:

Primero, definí mi tipo de columna especial:

class SpecialColumn(object): pass

Luego, definí una metaclase heredando de DeclarativeMeta que escanea la clase para las instancias de SpecialColumn y las reemplaza con dos Column y una propiedad híbrida (definida como un cierre):

class MyDeclarativeMeta(DeclarativeMeta): def __new__(cls, name, bases, attrs): for name, col in attrs.items(): if isinstance(col, SpecialColumn): # Replacing the column del attrs[name] col1_name = ''_{0}_1''.format(name) col2_name = ''_{0}_2''.format(name) attrs[col1_name] = Column(...) attrs[col2_name] = Column(...) # Adding the hybrid property def getter(self): return (getattr(self, col1_name), getattr(self, col2_name)) attrs[name] = hybrid_property(getter)

Y finalmente construí una instancia de declarative_base con ella, y dejé que el usuario definiera las clases con la nueva base:

MyBase = declarative_base(metaclass=MyDeclarativeMeta) class MyClass(MyBase): col1 = SpecialColumn() col2 = Column(...)

Ahora para mis preguntas: En primer lugar, ¿es correcto mi enfoque? En segundo lugar, ¿cómo puedo usar la metaclase para agregar el colocador? ¿Sería correcto hacer lo siguiente?

def setter(self, (v1, v2)): setattr(self, col1_name, v1) setattr(self, col2_name, v2)

Y luego simplemente haz attrs[name].setter(setter) ?