Отношение SQLAlchemy один к одному в унаследованной таблице создает несколько строк - PullRequest
0 голосов
/ 09 мая 2020

WorkoutRating наследуется от Rating. Когда вы создаете рейтинг тренировки, строка вставляется в Rating и WorkoutRating с тем же id. WorkoutRating и Workout взаимосвязаны один-к-одному, но когда рейтинг тренировки создается, он вставляет новую строку в таблицу WorkoutRating и устанавливает workout_id null для старого рейтинга. Вместо этого я бы хотел, чтобы он обновил старый рейтинг. Я знаю, что могу сделать это в коде, но мне интересно, почему не работает однозначное отношение.

Также есть класс WOTrainerRating, который наследуется от Rating и создается, когда WorkoutRating равен создан. Он также вставляет новую строку с тем же workout_id, но не удаляет workout_id в старой записи. (Я думаю, это потому, что на Workout нет связи.) Я не думаю, что это влияет на поведение WorkoutRating, но я включил его на всякий случай.

BasicMixin и PolymorphicMixin - объекты с некоторыми методами и свойствами, ни один из которых здесь не используется. put() - это удобный метод, который добавляет и фиксирует один элемент в сеансе базы данных. Я пропустил столбцы, не относящиеся к этому вопросу.

class Workout(BasicMixin, Base):
    user_id = Column(
        Integer, ForeignKey('users.id', ondelete='CASCADE'), index=True)
    user = relationship('User', foreign_keys=[user_id], backref='workouts')
    rating = relationship('WorkoutRating', uselist=False, back_populates='workout')
    ....


class Rating(PolymorphicMixin, Base):
    __mapper_args__ = {
        'polymorphic_on': discriminator,
        'polymorphic_identity': 'rating'
    }
    id = Column(Integer, primary_key=True)
    user_id = Column(Integer, ForeignKey('users.id', ondelete='CASCADE'), index=True)
    user = relationship('User')
    discriminator = Column('type', String(50))
    rating = Column(SmallInteger)
    ....


class WOTrainerRating(Rating):
    __tablename__ = 'workout_trainers_ratings'
    __mapper_args__ = {'polymorphic_identity': 'trainer'}
    id = Column(
        Integer,
        ForeignKey('ratings.id', ondelete='CASCADE'),
        primary_key=True)
    trainer_id = Column(
        Integer, ForeignKey('users.id', ondelete='CASCADE'))
    trainer = relationship('User', backref='ratings')
    workout_id = Column(
        Integer, ForeignKey('workouts.id', ondelete='CASCADE'))
    workout = relationship('Workout', backref='trainer_ratings')
    workout_rating_id = Column(
        Integer, ForeignKey('workouts_ratings.id', ondelete='CASCADE'))
    workout_rating = relationship(
        'WorkoutRating',
        backref=backref(
            'trainer_rating', cascade="all, delete-orphan", uselist=False),
        foreign_keys=[workout_rating_id])


class WorkoutRating(Rating):
    __tablename__ = 'workouts_ratings'
    __mapper_args__ = {'polymorphic_identity': 'workout'}
    id = Column(
        Integer,
        ForeignKey('ratings.id', ondelete='CASCADE'),
        primary_key=True)
    workout_id = Column(
        Integer, ForeignKey('workouts.id', ondelete='CASCADE'),
        index=True)
    workout = relationship('Workout', back_populates='rating')
    ...

    @classmethod
    def rate(
            cls,
            user,
            workout,
            rating,
            trainer_rating=None,
            ...):

        if trainer_rating:
            trainer_rating = WOTrainerRating(
                user=user,
                rating=trainer_rating,
                trainer_id=template.trainer.id,
                workout_id=workout.id)

        rating = put(cls(
            user=user,
            workout=workout,
            trainer_rating=trainer_rating,
            rating=rating))  # rating here is an integer (Rating.rating)
        return rating
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...