Byłem absolutnie dręczący mój mózg nad tym i nie mogę wydawać się wypracowywać jak obejść problem. Należy pamiętać, że mam wyciąć dużo dziedzinach niezwiązanych z moich modeliDziedziczenie + zagraniczne klucze
Jestem w środku kodowania moje modele SQL Alchemy, i napotkał następujący problem:
Ze względu na wielu systemach rozliczeniowych, za każdym z zupełnie innymi atrybutami, a ze względu na różne typy atrybutów subskrypcji (tj. nazwy użytkowników, lokalizacje węzłów itp.) musiałem zejść po polimorficznej drodze dziedziczenia.
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'}
Wszystko działa dobrze, z wyjątkiem jednej rzeczy.
Powiedzmy, że mogę uruchomić następujące:
>>> a = Product1()
>>> b = BillingSystem.objects.get(1)
>>> a.billing_system = b
>>> session.add(a)
>>> session.commit()
będę następujący komunikat o błędzie.
sqlalchemy.exc.ProgrammingError: (ProgrammingError) can't adapt type 'BillingSystem1' 'INSERT INTO
Rozumiem, co mówi, a próbowałem następujące.
>>> a.billing_system = b.id
To tylko przechowuje identyfikator, a gdy próbuję retreive wiązany obiekt, to zamiast otrzymać całkowitą. To wymaga ode mnie dodatkowego zapytania. Spodziewałbym się, że to nie jest droga.
Próbowałem również dodawanie kluczy obcych dla wszystkich identyfikatorów systemu billingowego do Produkt1 model
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)
To również nie działa w ogóle, a ja otrzymałem ten sam wyjątek ProgrammingError stwierdzający, że typ może dostosuj się.
Mam trawled instrukcję, a nie mogę znaleźć jak to zrobić, ale trzeba jakąś formę opcji magicznego do tego dopuścić:
>>> a = BillingSystem.query.get(1)
>>> type(a)
BillingSystem
Zamiast:
>>> a = BillingSystem.query.get(1)
>>> type(a)
BillingSystem1
Czy ktoś jest w stanie rzucić jakiekolwiek światło na to, w jaki sposób mogę wysłać zapytanie do mojego zestawu modeli polimorficznych o identyfikator i uzyskać tylko klasę modelu podstawowego?
Uważam, że rozwiąże to mój problem, nie jestem pewien, jak go rozwiązać.
Dzięki za poświęcenie czasu na przeczytanie tego, a ja naprawdę chciałbym dowiedzieć się, gdzie idę źle (zbyt długo czułem się tak długo, więc to nie pomaga).
Cheers, Rhys
To prawdopodobnie nie będzie to odpowiedź super pomocne dla ciebie, ale wydaje się, że aby dowiedzieć się, czy mogę ci pomóc, będę musiał czytać Ogromna ilość twojego kodu i wymyśl małe szczegóły. Najlepszym sposobem uzyskania odpowiedzi na tej stronie jest podanie kodu w dół, aż stanie się niewiarygodnie prosty, ale nadal daje ten sam błąd. Następnie możesz zadać bardzo konkretne pytanie: "dlaczego linia 3 tych 4 linii kodu powoduje błąd?" Jako dodatkowy bonus zazwyczaj * rozwiązujesz * problem, kiedy przechodzisz przez ten proces. Powodzenia! –
Trochę odpoczynku i twoja rada pomogły dużo! Dziękuję Ci :) –