Hello everyone,

I am modelling a relationship between two groups which is a many-to-many 
relationship, with an additional constraint.
I have an Employer and a Worker class. Employers can have a relationship to 
a worker in a number of ways, which
I'm representing by an enum: Contractor, Employee, Part-Time etc.
The join table has three columns, employer_id, worker_id and worker_type, 
which is the enum value.

The below code works for creating the relationship, but I don't quite 
understand how to query it.

I create an employer, and then a worker.
Then I use
employer.contractor.append(worker)

The join table contains the correct ids and the 'CONTRACTOR' enum value.
But when I iterate through employer.part_time, I get back the same worker 
who is a 'CONTRACTOR'. I'm expecting that only
employer.contractor should contain values, and that employer.employee and 
employer.part_time should be empty.

Is there something corresponding to *creator* that can be used when 
retrieving the values?
Or, what is the best way for me to get back the correct values? Do I need 
to issue a query, and with what parameters?


from sqlalchemy import Column, ForeignKey, Enum, Text, Integer, 
create_engine
from sqlalchemy.orm import relationship, backref, sessionmaker, 
scoped_session
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.declarative import declarative_base
from enum import Enum as eEnum


Base = declarative_base()

class WorkerType(eEnum):
    CONTRACTOR = 0
    EMPLOYEE = 1
    PART_TIME = 2

class Employer(Base):
    __tablename__ = "employer"

    id = Column(Integer, primary_key=True)
    name = Column(Text)

    contractor = association_proxy(
        "employer_workers", "worker",
        creator=lambda el:EmployerWorkerAssociation(
            worker=el,
            worker_type=WorkerType.CONTRACTOR
        )
    )

    employee = association_proxy(
        "employer_workers", "worker",
        creator=lambda el:EmployerWorkerAssociation(
            worker=el,
            worker_type=WorkerType.EMPLOYEE
        )
    )

    part_time = association_proxy(
        "employer_workers", "worker",
        creator=lambda el:EmployerWorkerAssociation(
            worker=el,
            worker_type=WorkerType.PART_TIME
        )
    )


class EmployerWorkerAssociation(Base):
    __tablename__ = "employer_to_worker"

    employer_id = Column(ForeignKey("employer.id"), primary_key=True)
    worker_id = Column(ForeignKey("worker.id"), primary_key=True)
    worker_type = Column(Enum(WorkerType), primary_key=True)

    employer = relationship(
        "Employer",
        backref=backref("employer_workers", cascade="all, delete-orphan")
    )

    worker = relationship(
        "Worker",
        backref=backref("worker_employers")
    )

class Worker(Base):
    __tablename__ = "worker"
    id = Column(Integer, primary_key=True)
    name = Column(Text)



engine = create_engine("sqlite://")
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = scoped_session(Session)

e1 = Employer(name="The Company")
session.add(e1)
session.commit()

w1 = Worker(name="The Programmer")
session.add(w1)
session.commit()

e1.contractor.append(w1)
session.add(e1)                                                             
                                                              44,0-1        
81%
session.commit()

# I'm expecting contractor=1 employee=0 part_time=0
print(f"Contractors: {len(e1.contractor)}")
print(f"Employees  : {len(e1.employee)}")
print(f"Part Timers: {len(e1.part_time)}")

# There shouldn't be anyone 'PART_TIME'
for worker in e1.part_time:
    print(f"{worker.id} {worker.name}")



Thank you for your time.

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to