让我们假设我使用一个小型Flask应用程序向办公室内的同事提供数据,让我们假设这是一个我没有明确“付钱做”的项目,所以我没有所有时间都在世界编写代码。
我在家里进行宠物项目试验时发现,不是用@app.route('/some/local/page')
装饰每一条最后一条路线,而是我可以做以下事情:
from flask import Flask, render_template, url_for, redirect, abort
from collections import OrderedDict
goodURLS = OrderedDict([('/index','Home'), ##can be passed to the template
('/about', 'About'), ##to create the navigation bar
('/foo', 'Foo'),
('/bar', 'Bar'), ##hence the use of OrderedDict
('/eggs', 'Eggs'), ##to have a set order for that navibar
('/spam', 'Spam')])
app = Flask(__name__)
@app.route('/<destination>')
def goThere(destination):
availableRoutes = goodURLS.keys():
if "/" + destination in availableRoutes:
return render_template('/%s.html' % destination, goodURLS=goodURLS)
else:
abort(404)
@app.errorhandler(404)
def notFound(e):
return render_template('/notFound.html'), 404
现在我需要做的就是更新我的一个列表,我的导航栏和路由处理功能都是锁定步骤。
或者,我已经编写了一种方法来确定可行的文件位置,方法是使用os.walk
和file.endswith('.aGivenFileExtension')
一起找到我想要访问的每个文件。然后可以将用户的请求与此函数返回的列表进行比较(这显然会更改serveTheUser()
函数。
from os import path, walk
def fileFinder(directory, extension=".html"):
"""Returns a list of files with a given file extension at a given path.
By default .html files are returned.
"""
foundFilesList = []
if path.exists(directory):
for p, d, files in walk(directory):
for file in files:
if file.endswith(extension):
foundFilesList.append(file)
return foundFilesList
goodRoutes = fileFinder('./templates/someFolderWithGoodRoutes/')
问题是,这是不是很糟糕?
我只是没有使用Flask的许多方面(主要是因为我还不需要了解它们) - 因此,与Flask的内置功能相比,这可能实际上是限制或冗余。我缺乏明确装饰每条路线是否让我失去了Flask的一大特色?
此外,这些方法中的任何一种或多或少比另一种更安全吗?我真的不太了解网络安全 - 就像我说的那样,现在这是所有办公室内的东西,我的数据的安全性由我们的IT专业人员保证,并且没有来自办公室以外的传入请求 - 但是一个现实世界的环境,这些都是有害的吗?特别是,如果我使用后端到os.walk
服务器本地磁盘上的某个位置,我不是要求它被一些不好的人滥用吗?
app.route
装饰每条可行的路线都是浪费时间。
答案 0 :(得分:0)
我假设根据你的代码,所有路由都有一个相同名称的相应模板文件(destination.html到destination.html),并且手动更改了goodURL菜单栏。一种更简单的方法是尝试在请求时呈现模板,如果不存在则返回404页面。
from jinja2 import TemplateNotFound
from werkzeug import secure_filename
....
@app.route('/<destination>')
def goThere(destination):
destTemplate = secure_filename("%s.html" % destination)
try:
return render_template(destTemplate, goodURLS=goodURLS)
except TemplateNotFound:
abort(404)
@app.errorhandler(404)
def notFound(e):
return render_template('/notFound.html'), 404
这改编自Stackoverflow: How do I create a 404 page?的答案。
编辑:更新以利用Werkzeug的secure_filename
来清理用户输入。
答案 1 :(得分:0)
在我看来,您的解决方案没有任何问题。问题是,通过这种设置,你可以做的事情非常有限。
我不确定你是否简化了要在此处显示的代码,但是如果你在视图函数中所做的只是收集一些数据,然后选择一个模板来渲染它,那么你也可以渲染整个事情在一个页面中,并可能使用Javascript选项卡控件将其分为客户端部分。
如果每个模板需要不同的数据,那么获取和处理每个模板的数据的逻辑必须在您的视图函数中,这看起来会非常混乱,因为您将拥有一长串if语句处理每个模板。在每个模板的单独视图函数和单独的视图函数之间,我认为后者会更快,如果你还考虑维护工作则会更快。
更新:根据评论中的转换,我支持我的回答,并提供一些小的保留。
我认为您的解决方案有效并且没有重大问题。我没有看到安全风险,因为您在使用它之前验证来自客户端的输入。
如果忽略顶部的导航栏,您只是使用Flask来提供可被视为静态的文件。您应该考虑使用像Frozen-Flask这样的扩展将Flask应用程序编译成一组静态文件,然后您只需使用常规Web服务器托管已编译的文件。当您需要添加/删除路线时,您可以修改Flask应用并再次编译。
另一个想法是,如果您需要添加服务器端逻辑,您的Flask应用程序结构将无法很好地扩展。现在你在服务器中没有任何逻辑,一切都是由jQuery在浏览器中处理的,所以只有一个视图功能才能正常工作。如果在某些时候你需要为这些页面添加服务器逻辑,那么你会发现这种结构不方便。
我希望这会有所帮助。