Flask url_for URLs in Javascript
使用flask时,在Javascript文件中创建动态URL的推荐方法是什么? 在jinja2模板和python视图中,使用url_for,在.js文件中执行此操作的推荐方法是什么? 由于模板引擎不会解释它们。
基本上想做的是:
1 2
| // in comments.js
$.post(url_for('comment.comment_reply')); |
这是不可能的。
但是自然地,我可以在模板中执行该操作:
1
| $.post(url_for('comment.comment_reply')); |
@dumbmatter的建议几乎被认为是事实上的标准方法。但是我认为会有更好的方法。所以我设法开发了这个插件:Flask-JSGlue。
添加{{ JSGlue.include() }}后,可以在源代码中执行以下操作:
1
| $.post(Flask.url_for('comment.comment_reply', {article_id: 3})); |
要么:
1
| location.href = Flask.url_for('index', {}); |
-
太棒了!正是我在2012年寻找的东西。:)我会更改接受的答案,因为这要好得多
-
这是否允许您在页面运行时使用javascript变量来指定用于构建url的url_for参数?这就是您的示例代码中的article_id所代表的意思吗?
-
是的,@ ThatAintWorking。可以与在Flask上的视图函数中使用的完全相同。它是一个客户端实现。
-
很抱歉,我应该回来并删除或更新我的评论。我在真正签出您的图书馆之前就发布了它。我已经在我的项目中使用它。感谢您的参与。
-
我喜欢这个主意!我无法使它工作。我在render_template方法中传递了jsglue变量,然后添加了此{{ JSGlue.include() }},但是当我尝试在JavaScript中使用Flask.url_for()时,得到了Uncaught ReferenceError: Flask is not defined。我完全有可能错过了某件事。无论如何,好东西!
-
@tmthyjames您不必在render_template方法中传递它;您只需使用Flask应用实例创建JSGlue实例,然后直接从模板中使用它即可。 JSGlue.include()只需添加标记即可在前端包含Flask javascript对象。希望您能正常工作!
-
这是非常好的解决方案。我无法更改脚本文件路径,在我的情况下为d3.json("{{url_for(static, filename=userdata0af968589866013dbe09f57d3c78cc094666ff49. json)}}", ,因为文件路径信息位于{{ url_for }}命令中,所以无法中断。但是,现在我可以将var usermusics定义为0afblahblah.json并像Flask.url_for("static", {"filename": usermusics})一样使用它
-
这看起来确实很方便,但是是否有人考虑过将Flask API的这一部分公开给公众带来安全性呢?
-
实际上,这甚至可能更糟:它实际上在JS文件中列出了所有端点以及有关其参数的信息。
-
如果仅包含由装饰器列入白名单的端点,则可以显着改善。
-
装饰器听起来不错。但是公平地说,不暴露端点不会使其安全。除了不公开端点外,您还必须具有某种身份验证/安全性。我认为这是一个行之有效的/更安全的方法。感谢您的输入,@ Collin。
-
太棒了!是的,我只是在谈论某人无权访问的端点。也就是说,如果他们尝试访问,将获得403/404 /重定向到登录页面。没有理由公开列出这些端点,并且公开列出它们可以使对手更容易找到安全漏洞(如果存在)。
-
@Collin在安全性方面,您通常会假设攻击者了解您的系统工作方式的所有知识(请注意,"系统的工作方式"确实排除了秘密密码,密钥等)。即使攻击者知道终点,您的系统也应该是安全的。还有其他获取方式,例如社会工程学,感染了合法的用户计算机,而且我确信清单还在继续。依靠不知道端点的攻击者是"通过隐蔽性实现安全性"的一种形式,并且在实践中,此类技术通常不能很好地抵御真正的攻击者。
-
@Collin还请记住,您的URL基本上是公共信息。您的许多用户都将了解它们,因此无论如何也很难对其进行保护。而且您实际上只公开了一种模式,因此攻击者仍然需要模式的输入。我不认为这种少量的信息公开会大大增加您的风险。
-
@ jpmc26你是绝对正确的,多数民众赞成在它应该如何工作。不幸的是,继承的代码库是一回事。
-
@Collin那就是您要问经理/客户的问题,"现在存在的该应用程序存在一些基本的安全缺陷,如果您重视自己的声誉,应立即解决。这是我的建议……"
-
我有一个问题:如何将Flask-JSGlue不在标准Flask应用程序上而是在套接字化的Flask-SocketIO应用程序上集成?我试图这样做没有运气,我已经在此链接上打开了一个问题-stackoverflow.com/questions/54310058/-如果有人知道如何做到这一点,我们将不胜感激
Flask文档建议在HTML文件中使用url_for来设置一个变量,该变量包含可以在其他位置访问的根URL。然后,您必须在此之上手动构建视图URL,尽管我想您可以将它们存储为类似于根URL的视图。
-
不是那么漂亮,但我想这一定要做!
-
现在,我再次考虑一下,是否有可能编写一个Flask扩展来查看Python代码中定义的URL路由并将其动态转换(无论何时发生更改)为等效的JavaScript代码,从而在JavaScript中提供等效的url_for ?
-
在答案中添加更多详细信息将很有帮助。我完全按照链接的建议进行操作,但是模板变量request.script_root|tojson|safe为我呈现了一个空字符串。不幸的是doc链接没有给出一个独立的示例,我无法弄清楚它隐含的假设...
-
是的,此外,如果您需要专门用于Javascript且不适合HTML模板的url_for,那么您可能应该编写一个小型JS库来执行AJAX请求。这个库可以从Jinja2动态创建的JSON中读取网址
在寻找解决方案时,他们提出了解决方案,其中
关键是要意识到Jinja2具有开箱即用地呈现javascript的能力。
将模板文件夹设置为如下所示:
1 2 3 4 5
| /template
/html
/index.html
/js
/index.js |
在您的views.py中
1 2 3
| @app.route("/index_js")
def index_js():
render_template("/js/index.js") |
现在,而不是从您的静态文件夹中提供JavaScript。您将使用:
1
| <script src="{{ url_for('index_js') }}"> |
毕竟,您是在动态生成JavaScript,它不再是静态文件。
现在,在您的javascript文件中,只需像在任何html文件中一样使用url_for。
例如,使用Jquery发出Ajax请求
1 2 3 4 5
| $.ajax({
url: {{ url_for('endpoint_to_resource') }},
method:"GET",
success: call_back()
}) |
-
Ive实际上使用了此解决方案,但重要的是要注意使用jinja2渲染所有javascript文件对性能的影响以及对缓存的潜在影响。
-
感谢您提供替代解决方案。请注意,您的视图功能中有一个错字。它应该是return render_template("jsindex.js")而不是render_template("jsindex.js")
@jeremy的答案是正确的,并且可能是更常用的方法,但是作为替代答案,请注意,dantezhu编写并发布了flask扩展,声称可以执行注释中建议的url-route-map-to-javascript转换。
我用这个肮脏和丑陋的把戏:
1 2
| "{{url_for('mypage', name=metadata.name,scale=93,group=2)}}"
.replace('93/group',scale+'/group') |
其中scale是我要用于AJAX请求的javascript变量。
因此,url_for生成一个URL,而JavaScript在运行时替换该参数。生成的代码类似于:
1
| "/ajaxservive/mynam/scale/93/group/2".replace('93/group',scale+'/group') |
这很奇怪,但是仍然找不到更优雅的解决方案。
实际上,查看链接的flask扩展的代码,它执行相同的操作,但是管理一般情况。
就我而言
我正在尝试动态创建网址
我按如下方式解决了我的问题(注意:我已将Angular的语法换成{[x]}:
1 2 3 4 5 6 7 8 9 10 11 12
| <ul>
<li ng-repeat="x in projects">
{[x.title]}
{% set url = url_for('static',filename="img/") %}
<img src="{{url}}{[x.img]}">
</li>
</ul> |
我试图在按下按钮时调用FLASK路线。它应该收集响应并更新div。该页面不应重新加载。
我用jQuery来做到这一点。
这是代码:
1 2 3
| @app.route('/<name>')
def getContent(name):
return 'This is %s' % name |
HTML:
1 2 3 4 5 6 7 8 9 10
| Count
<button id="next_id" class="btn btn-primary">Press</button>
$('#next_id').click(function (){
$.get('/aroy', function(data, status){
$('#mySpace').html(data);
});
}); |
我建议这样:
1
| <script src="{{ url_for('static', filename='js/jquery.js') }}" type="text/javascript"> |
对我来说很好