【问题标题】:How Do I Increment My View Counter in Flask?如何在 Flask 中增加我的查看计数器?
【发布时间】:2018-12-30 09:37:37
【问题描述】:

我在做什么的总结和背景:

我正在创建一个应用程序,它允许您添加和存储食谱,并且我希望能够使用每个食谱收到的观看次数来组织我的食谱列表。我应该解释一下,我有一个食谱列表,如果您单击该列表中一个食谱的标题,它将带您进入一个新页面并显示该食谱。这样,我可以将我的应用程序组织成三类列表(早餐、午餐和晚餐)。

我正在使用 MongoDB 来托管我的键/值对 ("views":0) 并且 我希望能够增加每次有人刷新页面时“浏览量”+1。我将在下面提供我的代码,但我认为我的问题是我似乎无法在我的 HTML 或 MongoDB 中增加值。让我解释一下:我几乎可以肯定我的路由代码是正确的。我看过很多关于在 MongoDB 中 $inc 一个值的适当方法的教程,但我相信我的 HTML 中遗漏了一些东西来正确对应该代码,我不确定它是什么是。

当我运行此代码时它仍然有效并且没有错误警告,但是当我进入任何食谱页面时,当我刷新该页面时视图计数器不会改变。它只是保持在 0。

我还应该说我有两条独立的路线,我认为在这种情况下它们彼此相关:我有一个“view_recipe”路线,它显示食谱的页面,我有一个“view_count”路线,它的功能是计算观看次数。我将在下面提供这两个以及我的 HTML 供大家检查。

到目前为止我所做的尝试:

对于我的食谱应用程序,我遵循了关于如何 $inc 我的键/值的 Youtube 教程,但是我不确定这是我需要提供给我的 HTML 的信息。根据其他例子,我在HTML中对应的视图信息是这样的:

<a href="{{url_for('view_recipe', recipe_id=recipe._id)}}" class="waves-effect waves-light btn btn_small blue">{{recipe.views})</a>

我已经为路线提供了一个 url_,并制作了我认为是相关的 recipe_id=recipe._id,就像我在其他示例中看到的那样,我用它来定位 id。

我的代码:

这是我的 "view_recipe""view_count" 路线:

@app.route('/view_recipe/<recipe_id>')
def view_recipe(recipe_id):
    the_recipe =  mongo.db.recipes.find_one({"_id": ObjectId(recipe_id)})
    return render_template('view_recipe.html', recipe=the_recipe)

@app.route('/view_count/<recipe_id>')
def view_count(recipe_id):
    mongo.db.recipes
    recipes.update({'_id': str(recipe_id)}, {'$inc': {'views': int(1)}})
    return url_for('view_recipe.html')

这是我在 "view_recipe.html" 中提供的查看次数部分,我在其中放置 {{recipe.view}}

<a href="{{url_for('view_recipe', recipe_id=recipe._id)}}" class="waves-effect waves-light btn btn_small blue">{{recipe.views})</a>

当我运行此代码时会发生什么与我预期会发生什么:

代码运行,但它并没有像我预期的那样增加。当我刷新页面时,计数器只是保持在 0 并且不会上升。我希望一旦页面被刷新,计数器的值将会增加并显示在浏览器中,并在我的 MongoDb 集合中更新。

以防万一……

如果您需要更多信息,或者我不够清楚或解释得不够清楚,请告诉我,我会改正的。

谢谢。

【问题讨论】:

  • 您拥有view_count 视图,但您无法访问它。您可能应该直接在 view_recipe 视图中增加计数器。
  • 感谢您的回复。也许我的措辞错误,但这就是我尝试过的:@app.route('/view_recipe/') def view_recipe(recipe_id): the_recipe = mongo.db.recipes.find_one({"_id": ObjectId (recipe_id)}, {'$inc': {'views': int(1)}}) return render_template('view_recipe.html', recipe=the_recipe) 我得到了这个错误: Unsupported projection option: $inc: {观看次数:1 }
  • 另外,很抱歉,我不确定如何在 cmets 中格式化代码。对不起,这很乱。
  • 我不熟悉 MongoDB,但您可能无法增加计数器并在一次查询中找到配方。尝试使用两条指令:the_recipe = mongo.db.recipes.find_one({"_id": ObjectId(recipe_id)}) 然后mongo.db.recipes.update({'_id': str(recipe_id)}, {'$inc': {'views': int(1)}})
  • 你也应该保持一致,在这两种情况下都使用ObjectId(recipe_id)str(recipe_id)

标签: python mongodb flask


【解决方案1】:

可能需要对 Mongo DB 的东西进行一些调整,但为什么不只使用没有路由的 view_count 函数,因为它不需要通过 URL 调用。而是直接在 view_recipe 函数中调用它。

@app.route('/view_recipe/<int:recipe_id>')
def view_recipe(recipe_id):
    the_recipe =  mongo.db.recipes.find_one({"_id": recipe_id})
    view_count(recipe_id) # call the other function here.
    return render_template('view_recipe.html', recipe=the_recipe)

def view_count(recipe_id):
    recipes = mongo.db.recipes
    recipes.update({'_id': recipe_id}, {'$inc': {'views': 1}})
    return True
  • 在路由中,参数应为&lt;int:recipe_id&gt;,以确保用户输入为整数。
  • 第二个函数不再需要返回render_template,而是返回True。
  • 您不能只在视图函数中调用mongo.db.recipes。我已对此进行了更改,因此您将receipes 设置为此,然后访问receipes.update。这与调用mongo.db.recipes.update() 相同

编辑

我假设您使用的是pymongo。注意上面的变化。

我很好奇,我启动了一个 mongo DB 测试盒并尝试了这个。我已经测试并上传了 this gist 和一个 shell.py 文件,该文件显示了我的初始配置,以及一个导入 db.py 的准系统烧瓶应用程序来演示这一点。

我认为你的问题是 ObjectID() 实际上做了一些不相关的事情。正如我的代码演示的那样,您应该只需要传递recipe_id。然后我可以执行几次curl http://localhost:5000/1 进行测试,并观察每次增加计数的开发服务器输出:

Db script:  {'_id': 1, 'text': 'TEST', 'counter': 5}
Flask says:  {'_id': 1, 'text': 'TEST', 'counter': 6}
127.0.0.1 - - [30/Dec/2018 01:22:21] "GET /1 HTTP/1.1" 200 -
Flask says:  {'_id': 1, 'text': 'TEST', 'counter': 7}
127.0.0.1 - - [30/Dec/2018 01:22:22] "GET /1 HTTP/1.1" 200 -
Flask says:  {'_id': 1, 'text': 'TEST', 'counter': 8}
127.0.0.1 - - [30/Dec/2018 01:22:22] "GET /1 HTTP/1.1" 200 -

【讨论】:

  • 看起来它可以很好地工作,你是对的,将这两个功能放在一条路线上更有意义。但是,当我尝试这样做时,我遇到了这个错误:'function' object has no attribute 'update'
  • 呃, 有必要吗? MongoDB 值设置为整数并且是页面刷新,所以我不知道如何以其他方式解释它。此外,我们在函数中将值指定为 int(1)。毋庸置疑,我仍在学习自己,但这似乎没有必要。
  • 查看variable rules,它提供了有关后者的更多信息。编辑:这实际上是在验证用户的输入,可能是任何东西。
  • 哦,够公平的。我不知道。尽管使用此代码,但我遇到了另一个错误:int() 参数必须是字符串或数字,而不是 'ObjectId'
  • 我仍然收到此错误:“int() 参数必须是字符串或数字,而不是 'ObjectId'”。如果我将我的 cloud9 工作空间分享给你看看会有帮助吗?
猜你喜欢
  • 1970-01-01
  • 2023-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-15
  • 2019-10-05
  • 1970-01-01
相关资源
最近更新 更多