В моем приложении для колб три модели 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
была бы очень признательна.В качестве альтернативы, если есть лучший способ добиться того, что я пытаюсь сделать, это также будет очень полезно.