Reputation: 21
I'm developing a DB where you at first register as a regular User
and subsequently become a Driver
. I'd like to create a Driver
object in SQL-Alchemy based on existing User
object. How can I achieve that?
Suppose that the User
table already has a user with ID=3. Now we would like to add a Driver
based on that user.
Here are classes that I used:
# Base class
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.String(MAX_NAME_LENGTH), nullable=False)
last_name = db.Column(db.String(MAX_SURNAME_LENGTH), nullable=False)
email = db.Column(db.String(MAX_EMAIL_LENGTH), nullable=False, unique=True)
# Child class
class Driver(User):
id = db.Column(db.Integer, db.ForeignKey(User.__tablename__ + '.id'), primary_key=True)
photo_url= db.Column(db.String(MAX_URL_LENGTH), nullable=False)
# ...
# we can easily add a new User
user = User(first_name='Martin', last_name='Smith', email='[email protected]')
db.session.add(user)
db.session.commit()
# But this code will create a new user and assign it to that driver instance!
# driver = Driver(# Will require fields of both User and Driver class #)
I expect to find some method for taking parent object and extending it with child's properties. Something like:
user_from_db = db.session.query(User).filter_by(User.id == 3).first()
driver = Driver(photo_url='/your_url/', based_on=user_from_db)
# And now driver has all properties of 'user_from_db'
# Furthermore, SQL-Alchemy would create a row only in `Driver` table
How can I accomplish that using SQL-Alchemy inheritance?
Upvotes: 1
Views: 1861
Reputation: 780
First I recommend making the following changes:
The autoincrement field is to leave the task of assigning an id to the database.
For all relationship (OneToMany, ManyToMany or OneToOne) you need to specify a db.relationship in the parent class. Read this.
And __tablename__
is optional, but sometimes flask throw an error if this is not assigned.
# Base class
class User(db.Model):
__tablename__ = 'user'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
first_name = db.Column(db.String(MAX_NAME_LENGTH), nullable=False)
last_name = db.Column(db.String(MAX_SURNAME_LENGTH), nullable=False)
email = db.Column(db.String(MAX_EMAIL_LENGTH), nullable=False, unique=True)
driver = db.relationship('Driver', backref='driver', lazy=True)
# Child class
class Driver(db.Model):
__tablename__ = 'driver'
id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True)
photo_url= db.Column(db.String(MAX_URL_LENGTH), nullable=False)
# ...
user = User(first_name='Martin', last_name='Smith', email='[email protected]')
db.session.add(user) # first we create a user and add him to the current session
db.session.flush() # here we says that db.session.add(user) is a pending transaction. More info [here][1]
driver = Driver(id=user.id, photo_url='/your_url/')
# and we pass as driver id the id of user previously created
db.session.add(driver) # add driver to current session
db.session.commit() # commits those changes to the database.
Upvotes: 1