Flask-SQLAlchemy: доступ к атрибутам SQLAlchemy и служебным программам управления состоянием - PullRequest
0 голосов
/ 17 сентября 2018

В моем приложении для колб три модели User, Task и Project.

Когда создается новый пользователь, автоматически создается проект с именем Inbox.Задачи, созданные без указанного проекта, автоматически назначаются для входящих пользователей, но пользователи могут создавать новые проекты и также добавлять задачи в эти проекты.

class Project(UserMixin, db.Model):
    __tablename__ = 'projects'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String)
    author_id = db.Column(db.Integer, db.ForeignKey('users.id'))
    author = db.relationship('User', foreign_keys=author_id, back_populates='projects')
    tasks = db.relationship('Task', foreign_keys='Task.project_id', back_populates='project')

    def __repr__(self):
        return '<Project %r>' % self.name

class Task(UserMixin, db.Model):
    __tablename__ = 'tasks'
    id = db.Column(db.Integer, primary_key=True)
    body = db.Column(db.String(128))
    due = db.Column(db.DateTime, index=True)
    done = db.Column(db.Boolean, default=False)
    author_id = db.Column(db.Integer, db.ForeignKey('users.id'))
    author = db.relationship('User', foreign_keys=author_id, back_populates='tasks')
    project_id = db.Column(db.Integer, db.ForeignKey('projects.id'))
    project = db.relationship('Project', foreign_keys=project_id, back_populates='tasks')

    def __init__(self, **kwargs):
        super(Task, self).__init__(**kwargs)
        if self.project is None:
            self.project = self.author.projects[0]

    def __repr__(self):
        return '<Task %r>' % self.id


class User(UserMixin, db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=True)
    email = db.Column(db.String(120), unique=True, nullable=True)
    password_hash = db.Column(db.String(80))
    confirmed = db.Column(db.Boolean, default=False)
    tasks = db.relationship('Task', foreign_keys=Task.author_id, back_populates='author')
    projects = db.relationship('Project', foreign_keys=Project.author_id, back_populates='author')

    def __init__(self, **kwargs):
        super(User, self).__init__(**kwargs)
        p = Project(name='Inbox', author=self)
        self.projects.append(p)


    def __repr__(self):
        return '<User {}>'.format(self.username)

Я хотел бы добиться следующего:

Если пользователь удаляет один из своих проектов, я бы хотел, чтобы все задачи были переназначены в папку «Входящие».Я попытался сделать это с помощью прослушивателей событий и следующего кода.

@db.event.listens_for(Project, 'after_delete')
def project_delete_listener(mapper, connection, project):
    print(project.id)
    @db.event.listens_for(db.session, "after_flush")
    def receive_after_flush(session, context):
        if len(project.tasks) != 0:
            for task in project.tasks:
                db.attributes.set_committed_value(task, project, task.author.projects[0])

Когда я делаю это, я получаю сообщение об ошибке: AttributeError: 'SQLAlchemy' object has no attribute 'attributes'

Документация для set_committed_value() заявляет, что к нему получают доступ: sqlalchemy.orm.attributes.set_committed_value(instance, key, value)

В документации Flask-SQLAlchemy говорится, что объект SQLAlchemy, который в моем случае db имеет всевспомогательные функции и атрибуты, такие как sqlalchemy и sqlalchemy.orm.Поэтому я ожидаю, что смогу получить доступ к db.attributes, однако это не представляется возможным.

Любая помощь по доступу к функции set_committed_value была бы очень признательна.В качестве альтернативы, если есть лучший способ добиться того, что я пытаюсь сделать, это также будет очень полезно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...