'sqlalchemy orm with complex foreign key construct
i want to make my first python program which uses sqlalchemy orm model, but i´m stuck for days now, i hope you can help me out.
I have a table which has 4 keyfields, where col 1 is also foreign key to table "User" col 2 AND col 3 are foreign keys to table "Bill_Pos" col 4 is foreign key to table "Products"
so in col 1 there can only be values which occur in the table user. in col 4 of course only values which occur in table products.
but in col 2 and col 3 there should be only values which occur in the same combination in table bill pos.
example - the yellow value should not be allowed
I know what i want but i am not able with the help-files, many hours and days with google to solve my problem.
Here´s the code:
from sqlalchemy import Column, Integer, REAL, String, DateTime, Boolean
from sqlalchemy.orm import registry
from sqlalchemy.orm import relationship
from sqlalchemy import ForeignKey
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy import ForeignKeyConstraint
from sqlalchemy import func
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import select
from sqlalchemy.exc import OperationalError
import keyboard
from os import system
import cl_password_services
Base = declarative_base()
class Info(Base):
__tablename__ = "info"
# Meta
id = Column(Integer, primary_key=True)
info = Column(String(25), nullable=False)
description = Column(String, nullable=False)
# Relations
user = relationship("User", back_populates="info")
bill_hdr = relationship("Bill_HDR", back_populates="info")
class User(Base):
__tablename__ = "user"
# Meta
id = Column(Integer, primary_key=True)
name = Column(String(30), unique=True, index=True, nullable=False)
password = Column(String(97))
info_id = Column(ForeignKey("info.id"), nullable=False)
# Relations
info = relationship("Info", back_populates="user")
add_data = relationship("Add_Data", back_populates="user")
count = relationship("Count", back_populates="user")
class Bill_HDR(Base):
__tablename__ = "bill_hdr"
# Meta
id = Column(Integer, primary_key=True)
timestamp = Column(DateTime, unique=True, nullable=False, default=func.now())
info_id = Column(ForeignKey("info.id"), nullable=False)
col4 = Column(Integer)
# Relations
info = relationship("Info", back_populates="bill_hdr")
bill_pos = relationship("Bill_Pos", back_populates="bill_hdr")
class Bill_Pos(Base):
__tablename__ = "bill_pos"
# Meta
id = Column(ForeignKey("bill_hdr.id"), primary_key=True)
pos = Column(Integer, primary_key=True)
# Relations
bill_hdr = relationship("Bill_HDR", back_populates="bill_pos")
add_data = relationship("Add_Data", back_populates="bill_pos")
class Products(Base):
__tablename__ = "products"
# Meta
id = Column(Integer, primary_key=True)
prod = Column(Integer, nullable=False)
pos = Column(Integer, nullable=False)
# Relations
add_data = relationship("Add_Data", back_populates="products")
class Add_Data(Base):
__tablename__ = "add_data"
# Meta
user_id = Column(ForeignKey("user.id"), primary_key=True)
bill_id = Column(ForeignKey("bill_pos.id"), primary_key=True)
bill_pos = Column(ForeignKey("bill_pos.pos"), primary_key=True)
prod_id = Column(ForeignKey("products.id"), primary_key=True)
info1 = Column(Integer)
info2 = Column(String)
info3 = Column(Boolean)
# Compound / Composite Foreign Keys
__table_args__ = (ForeignKeyConstraint(["bill_id", "bill_pos"], ["bill_pos.id", "bill_pos.pos"]), {})
#__table_args__ = (ForeignKeyConstraint(["bill_id", "bill_pos.id"], ["bill_pos", "bill_pos.pos"]), {})
#__table_args__ = (ForeignKeyConstraint(["bill_id"], ["bill_pos.id"],
# ["bill_pos"], ["bill_pos.pos"]), {})
#__table_args__ = (ForeignKeyConstraint(['user_id'], ['user.id'], ["bill_id"], ["bill_pos.id"], ["bill_pos"], ["bill_pos.pos"], ["prod_id"], ["products.id"]), )
user = relationship("User", back_populates="add_data")
products = relationship("Products", back_populates="add_data")
class Count(Base):
__tablename__ = "count"
# Meta
user_id = Column(ForeignKey("user.id"), primary_key=True)
prod = Column(ForeignKey("products.prod"), primary_key=True)
count = Column(Integer, nullable=False)
# Relations
user = relationship("User", back_populates="count")
products = relationship("Products", back_populates="count")
class DB:
def __init__(self):
self.engine = create_engine("sqlite+pysqlite:///:memory:", echo=True, future=True)
# DB-Kind & DB-API in RAM Logging=On 2.0 Style enabled
self.mapper_registry = registry()
self.Session = sessionmaker(bind=self.engine, future=True)
def create_tables_db(self):
# Tabellen anlegen von ORM Klassenobjekten
with self.engine.begin() as connection:
Base.metadata.create_all(connection)
def fill_some_data(self):
this_works = True
#try:
# if this_works:
# info_1 = Info(id=1, info="first", description="description first line")
# info_2 = Info(id=2, info="second", description="description 2nd line")
# info_3 = Info(id=3, info="third", description="description 3rd line")
# info_4 = Info(id=4, info="fourth", description="description 4th line")
# with self.Session() as session:
# session.add(info_1)
# session.add(info_2)
# session.add(info_3)
# session.add(info_4)
#except Exception as e:
# print("oh no")
if this_works:
info_1 = Info(id=1, info="first", description="description first line")
info_2 = Info(id=2, info="second", description="description 2nd line")
info_3 = Info(id=3, info="third", description="description 3rd line")
info_4 = Info(id=4, info="fourth", description="description 4th line")
with self.Session() as session:
session.add(info_1)
session.add(info_2)
session.add(info_3)
session.add(info_4)
mydb = DB()
mydb.create_tables_db()
mydb.fill_some_data()
print("END")
I tried many different ways but now i´m so exhausted i feel like i need a hint. I hope here´s someone how understand the Problem and can help me out.
P.S.: the example behind is not part of the discussion, I need a technical fix for this problem. Of course you can question that as well, but anyways i´m very interested in a solution for the question above. Thanks a lot in advance for your time and hopefully for a solution.
Edit: it might not work without association table? This is pushing me to my limits :-) / :-(
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|