He estado pensando en esto por completo, y parece que no se me ocurre cómo solucionar el problema. Tenga en cuenta que he cortado una gran cantidad de campos irrelevantes fuera de mis modelosHerencia + Claves foráneas
estoy en el medio de la codificación de seguridad de mis modelos SQL-Alchemy, y he encontrado el problema siguiente:
Debido a múltiples sistemas de facturación, cada con atributos completamente diferentes, y debido a los diferentes tipos de atributos de Suscripción (es decir, nombres de usuario, ubicaciones de nodos, etc.), he tenido que bajar por la ruta de herencia polimórfica.
class Subscription(Base):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(255))
secret = db.Column(postgresql.BYTEA)
type = db.Column(SubscriptionType.db_type())
status = db.Column(StatusType.db_type())
subscription_id = db.Column(db.Integer)
__tablename__ = 'subscription'
__table_args__ = {'schema':'public'}
__mapper_args__ = {'polymorphic_on' : type}
def __repr__(self):
return '<Subscription: %r>' % self.id
class Product1(Subscription):
__mapper_args__ = {'polymorphic_identity' : SubscriptionType.product1}
id = db.Column(db.Integer, db.ForeignKey('public.subscription.id'),
primary_key = True)
billing_system = db.Column(
db.Integer,
db.ForeignKey('public.billing_system.id')
)
class BillingSystem(Base):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(255))
type = db.Column(BillingSystemType.db_type())
__tablename__ = 'billing_system'
__table_args__ = {'schema':'public'}
__mapper_args__ = {'polymorphic_on' : type}
def __repr__(self):
return '<Subscription: %r>' % self.id
class BillingSystem1(BillingSystem):
__mapper_args__ = {'polymorphic_identity' : BillingSystemType.billingsystem1}
id = db.Column(db.Integer, db.ForeignKey('public.billing_system.id'),
primary_key = True)
billing_system = db.Column(
db.Integer,
db.ForeignKey('public.billing_system.id')
)
foo = db.Column(db.Integer)
bar = db.Column(db.Integer)
class BillingSystem2(BillingSystem):
__mapper_args__ = {'polymorphic_identity' : BillingSystemType.billingsystem2}
id = db.Column(db.Integer, db.ForeignKey('public.billing_system.id'),
primary_key = True)
billing_system = db.Column(
db.Integer,
db.ForeignKey('public.billing_system.id')
)
bing = db.Column(db.Integer)
boo = db.Column(db.Integer)
__tablename__ = 'billing_system_product2'
__table_args__ = {'schema':'public'}
Todo funciona bien, excepto por una cosa.
decir que corro el siguiente:
>>> a = Product1()
>>> b = BillingSystem.objects.get(1)
>>> a.billing_system = b
>>> session.add(a)
>>> session.commit()
que recibirá el siguiente error.
sqlalchemy.exc.ProgrammingError: (ProgrammingError) can't adapt type 'BillingSystem1' 'INSERT INTO
Entiendo lo que está diciendo, y he intentado lo siguiente.
>>> a.billing_system = b.id
Esto sólo almacena la identificación, y cuando intento retreive el objeto asociado, I en vez recibo un número entero. Esto implica que tengo que hacer una consulta adicional. Esperaría que este no sea el camino a seguir.
También he intentado añadir claves externas para todos los ID de sistema de facturación a la producto1 Modelo
class BillingSystem1(BillingSystem):
__mapper_args__ = {'polymorphic_identity' : BillingSystemType.billingsystem1}
id = db.Column(db.Integer, db.ForeignKey('public.billing_system.id'),
primary_key = True)
billing_system = db.Column(
db.Integer,
db.ForeignKey('public.billing_system.id'),
db.ForeignKey('public.billing_system1.id'),
db.ForeignKey('public.billing_system2.id'),
)
foo = db.Column(db.Integer)
bar = db.Column(db.Integer)
Esto también no funcionaba en absoluto, y he recibido la misma excepción ProgrammingError indicando que el tipo puede se adapta
He rastreado el manual, y no puedo encontrar la manera de hacerlo, pero necesito algún tipo de opción mágico para permitir que esto suceda:
>>> a = BillingSystem.query.get(1)
>>> type(a)
BillingSystem
En lugar de:
>>> a = BillingSystem.query.get(1)
>>> type(a)
BillingSystem1
¿Alguien puede arrojar alguna luz sobre cómo puedo consultar mi conjunto de modelos polimórficos para obtener una ID, y solo obtener la clase del modelo base?
Creo que esto resolverá mi problema, simplemente no estoy seguro de cómo resolverlo.
Gracias por tomarse el tiempo para leer esto, y realmente me gustaría saber dónde estoy yendo mal (también he estado despierto demasiado tiempo, por lo que no está ayudando).
Saludos, Rhys
Esto probablemente no va a ser una respuesta súper útil para usted, pero parece que con el fin de averiguar si te puedo ayudar, voy a tener que leer una gran cantidad de tu código y resuelve pequeños detalles. La mejor manera de obtener una respuesta en este sitio es reducir el código hasta que sea increíblemente simple, pero igual da el mismo error. Luego puede hacer una pregunta muy específica: "¿por qué la línea 3 de estas 4 líneas de código arroja un error?" Como una ventaja adicional, en realidad * soluciona el problema * cuando pasa por este proceso. ¡Buena suerte! –
¡Descanse un poco y su consejo ayudó mucho! Gracias :) –