Создать дочерний объект на основе родительского - PullRequest
1 голос
/ 13 октября 2019

Я занимаюсь разработкой БД, в которой вы сначала регистрируетесь как обычный User, а затем становитесь Driver. Я хотел бы создать объект Driver в SQL-Алхимии на основе существующего объекта User. Как мне этого добиться?

Предположим, что в таблице User уже есть пользователь с ID = 3. Теперь мы хотели бы добавить Driver на основе этого пользователя.

Вот классы, которые я использовал:

# 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='m.smith@gmail.com')
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 #)

Я ожидаю найти какой-нибудь метод для взятия родительского объектаи расширяя его свойствами ребенка. Что-то вроде:

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

Как мне добиться этого с помощью наследования SQL-Alchemy?

1 Ответ

0 голосов
/ 13 октября 2019

Сначала я рекомендую внести следующие изменения:
Поле автоинкремента должно оставить задачу назначения идентификатора для базы данных.
Для всех отношений (OneToMany, ManyToMany или OneToOne) вам необходимо указать db.relationship в родительском классе. Прочитайте это .
И __tablename__ необязательны, но иногда колба выдает ошибку, если это не назначено.

# 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='m.smith@gmail.com')
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.
...