我开始使用Mega Flask教程来构建一个简单的博客风格网站.我用这个与一些python学习相关,试图加强我学到的东西.为了更多地学习,我决定将教程弃用OAuth登录文章转换为传统的登录栏.当我尝试登录时,我遇到了一个问题.
NoForeignKeysError:无法确定关系User.posts上的父/子表之间的连接条件 - 没有链接这些表的外键.确保引用列与ForeignKey或ForeignKeyConstraint相关联,或指定"primaryjoin"表达式.
由于我对Python的理解有限,我在这里遇到了一个很大的障碍.我似乎无法弄清楚我做错了什么.
这是我的models.py文件.
followers = db.Table('followers', db.Column('follower_id', db.Integer, db.ForeignKey('user.id')), db.Column('followed_id', db.Integer, db.ForeignKey('user.id')) ) class User(db.Model): __tablename__ = "users" id = db.Column(db.Integer, primary_key=True) nickname = db.Column(db.String(64), index=True, unique=True) email = db.Column(db.String(120), index=True, unique=True) password = db.Column(db.String(100)) posts = db.relationship('Post', backref='author', lazy='dynamic') about_me = db.Column(db.String(140)) last_seen = db.Column(db.DateTime) followed = db.relationship('User', secondary=followers, primaryjoin=(followers.c.follower_id == id), secondaryjoin=(followers.c.followed_id == id), backref=db.backref('followers', lazy='dynamic'), lazy='dynamic') #reviews = db.relationship('Review', backref='author', lazy='dynamic') This is the review connectino for the user. @staticmethod def make_unique_nickname(nickname): if User.query.filter_by(nickname=nickname).first() is None: return nickname version = 2 while True: new_nickname = nickname + str(version) if User.query.filter_by(nickname=new_nickname).first() is None: break version += 1 return new_nickname def is_authenticated(self): return True def is_active(self): return True def is_anonymous(self): return False def get_id(self): try: return unicode(self.id) #python 2 except: return str(self.id) #python 3 def follow(self, user): if not self.is_following(user): self.followed.append(user) return self def unfollow(self, user): if self.is_following(user): self.followed.remove(user) return self def is_following(self, user): return self.followed.filter( followers.c.followed_id == user.id).count() > 0 def followed_posts(self): return Post.query.join( followers, (followers.c.followed_id == Post.user_id)).filter( followers.c.follower_id == self.id).order_by( Post.timestamp.desc()) def __repr__(self): return ''.format(self.nickname) class Post(db.Model): id = db.Column(db.Integer, primary_key=True) body = db.Column(db.String(140)) timestamp = db.Column(db.DateTime) user_id = db.Column(db.Integer, db.ForeignKey('user.id')) def __repr__(self): return ' '.format(self.body)
这是我的views.py文件,应包含相关代码:
#This loads the user from the database @lm.user_loader def load_user(id): return User.query.get(int(id)) @app.before_request def before_request(): g.user = current_user if g.user.is_authenticated: g.user.last_seen = datetime.utcnow() db.session.add(g.user) db.session.commit() @app.errorhandler(404) def not_found_error(error): return render_template('404.html'), 404 @app.errorhandler(500) def internal_error(error): db.session.rollback() return render_template('500.html'), 500 @app.route('/') @app.route('/index') @login_required def index(): user = g.user posts = [ #fake array of posts { 'author': {'nickname': 'Zach'}, 'body': 'Reviewed this product!' }, { 'author': {'nickname': 'Mark'}, 'body': 'I like buttcheese!' } ] return render_template('index.html', title='Home', user=user, posts=posts) @app.route('/login', methods=['GET', 'POST']) def login(): if g.user is not None and g.user.is_authenticated: return redirect(url_for('index')) form = LoginForm() if form.validate_on_submit(): user = User.query.get(form.nickname.data) session['remember_me'] = form.remember_me.data if user: if check_password_hash(user.password, form.password.data): user.authenticated = True db.session.add(user) db.session.commit() login_user(user, remember=True) flash("you've been logged in!, 'success'") return redirect(url_for('index')) else: flash('your email or password doesnt match!', 'error') return render_template('login.html', title='Sign In', form=form) @app.route('/logout') def logout(): logout_user() return redirect(url_for('index'))
我真的很挣扎,因为我还不太了解数据库关系.这是一次很棒的学习经历,但如果有人可以提供帮助,那就太棒了.
除了上面的帖子,我相信我已经解决了这个问题.我注意到我的tablename实际上是"用户"而不是"用户".因此,我需要将所有外键从user.id更改为users.id,因为它正在寻找一个名为"user"的表,该表不存在.