【发布时间】:2018-12-30 16:28:00
【问题描述】:
我正在尝试在 Flask 中创建一个待办事项列表应用程序。我对 Python 有很多经验,但对 Flask 框架还是很陌生。
我有 3 个模型 - 用户、任务和项目,我希望有一个名为 Inbox 的默认项目,每个用户甚至在自己创建任何项目之前都拥有该项目。
用户和项目通过多对多关系关联。
我对此的尝试是在一个函数上使用以下装饰器,该函数创建一个名为 Inbox 的新项目。
@event.listens_for(Project.__table__, 'after_create')
def create_inbox(*args, **kwargs):
inbox = Project(name='Inbox')
db.session.add(inbox)
db.session.commit()
然后,当我创建一个新用户时,我在 __init__ 函数中将“收件箱”项目添加到他们的项目中。
这个类只是用来建立用户和项目之间的多对多关系:
class UserProject(UserMixin, db.Model):
__tablename__ = 'userprojects'
project_id = db.Column(db.Integer, db.ForeignKey('projects.id'), primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), primary_key=True)
这是监听表创建的项目模型和装饰器:
class Project(UserMixin, db.Model):
__tablename__ = 'projects'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(32))
tasks = db.relationship('Task', backref='project', lazy='dynamic') # one project has many tasks
users = db.relationship('User', secondary='userprojects', lazy='dynamic', backref=db.backref('user', lazy='dynamic'))
@event.listens_for(Project.__table__, 'after_create')
def create_inbox(*args, **kwargs):
inbox = Project(name='Inbox')
db.session.add(inbox)
db.session.commit()
这是用户模型:
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(128))
tasks = db.relationship('Task', backref='author', lazy='dynamic') # one user has many tasks
projects = db.relationship('Project', secondary='userprojects', lazy='dynamic', backref=db.backref('project', lazy='dynamic'))
def __init__(self, **kwargs):
super(User, self).__init__(**kwargs)
p = Project.query.first()
if p not in self.projects.all():
self.projects.append(p)
还有一个任务模型,但我没有将其包含在此处,因为它与问题无关。
出现的问题是当我尝试使用迁移和升级时。我执行flask db init,迁移和升级并得到以下输出,所以看起来一切正常,迁移文件看起来很好。
flask db init
Creating directory /Users/Jasmine/projects/flask/tasky/migrations ... done
Creating directory /Users/Jasmine/projects/flask/tasky/migrations/versions ... done
Generating /Users/Jasmine/projects/flask/tasky/migrations/script.py.mako ... done
Generating /Users/Jasmine/projects/flask/tasky/migrations/env.py ... done
Generating /Users/Jasmine/projects/flask/tasky/migrations/README ... done
Generating /Users/Jasmine/projects/flask/tasky/migrations/alembic.ini ... done
Please edit configuration/connection/logging settings in '/Users/Jasmine/projects/flask/tasky/migrations/alembic.ini' before proceeding.
flask db migrate
INFO [alembic.runtime.migration] Context impl SQLiteImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
INFO [alembic.autogenerate.compare] Detected added table 'projects'
INFO [alembic.autogenerate.compare] Detected added table 'users'
INFO [alembic.autogenerate.compare] Detected added table 'tasks'
INFO [alembic.autogenerate.compare] Detected added index 'ix_tasks_due' on '['due']'
INFO [alembic.autogenerate.compare] Detected added table 'userprojects'
Generating /Users/Jasmine/projects/flask/tasky/migrations/versions/64311763e16f_creating_the_tables.py ... done
flask db upgrade
INFO [alembic.runtime.migration] Context impl SQLiteImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
INFO [alembic.runtime.migration] Running upgrade -> 64311763e16f, creating the tables
但是,当我进入 flask shell 并输入 Project.query.all() 时,我会得到一个空列表,我希望在其中得到一个包含一个项目的列表 - 一个名为“收件箱”的项目。
我不确定错误出在哪里,因此我们将不胜感激任何有关此问题的建议。
【问题讨论】:
-
也许我误解了,但你最好使用
after_insert并为收件箱创建一个Project实例并在插入时将其添加到新创建的User对象中吗? -
感谢@SuperShoot 的评论。我以前没有遇到过
after_insert,但会看看它是否有效。为什么会比使用after_create更好? -
因为它是一个绑定到创建新实例的事件,而
after_create绑定到发布创建表语句。每个用户都会有自己独特的收件箱实例吗?还是他们都共享同一个收件箱? IE。如果一个用户更改了他们的,所有其他用户都会看到更改吗?还是只有做出更改的用户? -
@SuperShoot 好的,我明白了。我确实希望每个用户都有自己独特的收件箱实例,因此使用
after_insert而不是after_create确实有意义。非常感谢。
标签: python-3.x flask sqlalchemy flask-sqlalchemy flask-migrate