Say I have a SqlAlchemy model something like this:
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, String, Integer, ForeignKey
from sqlalchemy.orm import sessionmaker, relationship
Base = declarative_base()
Session = sessionmaker()
class EmployeeType(Base):
__tablename__ = 'employee_type'
id = Column(Integer(), primary_key=True)
name = Column(String(20))
class Employee(Base):
__tablename__ = 'employee'
id = Column(Integer(), primary_key=True)
type_id = Column(Integer(), ForeignKey(EmployeeType.id))
type = relationship(EmployeeType, uselist=False)
session = Session()
session.add(EmployeeType(name='drone'))
session.add(EmployeeType(name='PHB'))
I'd like to have some kind of "relationship" from Employee directly to EmployeeType.name as a convenience, so I can skip the step of looking up an id or EmployeeType object if I have a type name:
emp = Employee()
emp.type_name = "drone"
session.add(emp)
session.commit()
assert (emp.type.id == 1)
Is such a thing possible?
EDIT: I found that association_proxy can get me partway there:
class Employee(Base):
...
type_name = association_proxy("type", "name")
the only problem being that if I assign to it:
emp = session.query(Employee).filter_by(EmployeeType.name=='PHB').first()
emp.type_name = 'drone'
it modifies the employee_type.name column, not the employee.type_id column.
You add a tags class variable to the Post model. You use the db. relationship() method, passing it the name of the tags model ( Tag in this case). You pass the post_tag association table to the secondary parameter to establish a many-to-many relationship between posts and tags.
The relationship function is a part of Relationship API of SQLAlchemy ORM package. It provides a relationship between two mapped classes. This corresponds to a parent-child or associative table relationship.
The comments class attribute defines a One-to-Many relationship between the Post model and the Comment model. You use the db. relationship() method, passing it the name of the comments model ( Comment in this case). You use the backref parameter to add a back reference that behaves like a column to the Comment model.
I agree with Jonathan's general approach, but I feel like adding an employee object to the session and setting the employee type should be independent operations. Here's an implementation that has type_name as a property and requires adding to the session before setting it:
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, String, Integer, ForeignKey
from sqlalchemy.orm import sessionmaker, relationship
Base = declarative_base()
Session = sessionmaker()
class EmployeeType(Base):
__tablename__ = 'employee_type'
id = Column(Integer(), primary_key=True)
name = Column(String(20))
class Employee(Base):
__tablename__ = 'employee'
id = Column(Integer(), primary_key=True)
type_id = Column(Integer(), ForeignKey(EmployeeType.id))
type = relationship(EmployeeType)
@property
def type_name(self):
if self.type is not None:
return self.type.name
return None
@type_name.setter
def type_name(self, value):
if value is None:
self.type = None
else:
session = Session.object_session(self)
if session is None:
raise Exception("Can't set Employee type by name until added to session")
self.type = session.query(EmployeeType).filter_by(name=value).one()
I would do this by creating a method that does this for me.
class EmployeeType(Base):
__tablename__ = 'employee_type'
id = Column(Integer(), primary_key=True)
name = Column(String(20))
class Employee(Base):
__tablename__ = 'employee'
id = Column(Integer(), primary_key=True)
type_id = Column(Integer(), ForeignKey(EmployeeType.id))
type = relationship(EmployeeType, uselist=False)
def __init__(self, type):
self.type = type
def add(self, type_name=None):
if type_name is not None:
emp_type = DBSession.query(EmployeeType).filter(EmployeeType.name == type_name).first()
if emp_type:
type = emp_type
else:
type = EmployeeType(name=type_name)
else:
type = None
DBSession.add(Employee(type=type))
Then you do:
Employee.add(type_name='boss')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With