Tweet Scheduler基于Flask Megatutorial:获取flask-sqlalchemy数据库字段的问题

时间:2018-06-13 18:35:14

标签: flask sqlalchemy flask-sqlalchemy twitter-oauth sqlalchemy-migrate

我正在修改在Miguel Grinberg的Flask Mega教程中创建的Flask应用程序,以便发布推文。我导入了tweepy来访问twitter api并修改了数据库以保存推文的预定时间。 我希望迭代current_user的帖子和SQLAlchemy数据库中的相应时间,并在当前时间与预定时间匹配时发布。

model.py中的数据库模型修改如下:

class Post(db.Model):
id = db.Column(db.Integer, primary_key = True)
body = db.Column(db.String(140))
timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
socialnetwork = db.Column(db.String(40))
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
#This is the stuff for scheduling, just date
hour = db.Column(db.Integer)
minute = db.Column(db.Integer)
day = db.Column(db.Integer)
month = db.Column(db.Integer)
year = db.Column(db.Integer)
ampm = db.Column(db.String(2))

就像测试一样,我想迭代当前用户的帖子并使用tweepy发布它们:

@app.before_first_request
def activate_job():
    def run_job():
        posts = current_user.followed_posts().filter_by(socialnetwork ='Twitter')
        for post in posts:
            tweepy_api.update_status(message)

            time.sleep(30)
    thread = threading.Thread(target=run_job)
    thread.start()

然而,这返回了错误:

AttributeError: 'NoneType' object has no attribute 'followed_posts'

在终端上。这让我感到困惑,因为我在同一个文件中多次使用current_user来过滤社交网络的帖子。

如下所示:routes.py

@app.route('/<username>')
@login_required
def user(username):
    user = User.query.filter_by(username = username).first_or_404()
    socialnetwork = request.args.get("socialnetwork")

    if socialnetwork == 'Facebook':

    posts = current_user.followed_posts().filter_by(socialnetwork = 'Facebook')

    elif socialnetwork == 'Twitter':
        posts = current_user.followed_posts().filter_by(socialnetwork = 'Twitter')
    else:
        posts = current_user.followed_posts()


    return render_template('user.html', user = user, posts = posts, form = socialnetwork)

上述情况不会产生任何错误,并且运作正常。

如果有人能说清楚我做错了什么,我会非常感激。

1 个答案:

答案 0 :(得分:0)

您可能会遇到问题,因为您尝试在其他线程上获取current_user(有关详细信息,请参阅Flask docs)。您在不具有任何当前用户的不同环境中呼叫run_job()(因为没有活动请求)。

我会重做它,以便您在主要帖子上获得当前用户的帖子(即在activate_job()中,然后将帖子列表传递给后台流程进行处理。< / p>

类似的东西:

def activate_job():
    posts = current_user.followed_posts().filter_by(socialnetwork ='Twitter')
    def run_job(posts):
        for post in posts:
            tweepy_api.update_status(message)

            time.sleep(30)
    thread = threading.Thread(target=run_job, args=[posts])
    thread.start()

值得注意的是,您可能想重新考虑整体方法。如果有任何预定的推文要发送,您应该使用某种独立于Web进程运行的后台任务队列,而不是检查每个请求。这样,您就不会对每个请求进行冗余检查,并且您不依赖于用户在预定时间内提出请求。

有关详情,请参阅The Flask Mega-Tutorial Part XXII: Background Jobs,然后查看Celery