Python /app1 中的 Bottle 应用程序 - 我是否被迫在所有路由前添加“/app1”?
Python Bottle app in /app1 - am I forced to prepend "/app1" to all routes?
我使用 运行() 在本地开发了一个 Bottle 应用程序,根据教程所有路由都以“/”开头,现在我想将它放在真实服务器上。
http://bottlepy.org/docs/dev/deployment.html 的文档建议使用 WSGIScriptAlias / /var/www/yourapp/app.wsgi
,但我不希望 WSGI 应用程序处理我网站的根目录。我希望站点的根由原始 Apache 处理,只有 /app1 下的 URL 由 WSGI 处理。
所以我将我的设置为 WSGIScriptAlias /app1 /var/www/app1/app1.py
。它 运行 在某种意义上,当我浏览到 server://app1 时,我可以看到我在 route('/') 下的 .py 文件中定义的内容,但是 none 的超链接有 / app1 前置,浏览器无法从 /var/www/app1/css 等中获取我的 css 文件
主题说明了一切。当我希望应用程序位于子目录中时,是否必须在所有路由前添加“/app1”?
我试图让自己面向未来,因为我预见到将来会制作 /app2、/app3 等。
编辑 1:为了实验,我 did 尝试将 /app1 添加到所有路由。结果更糟:我尝试浏览 /app1 下的每个地址都会出现 404 错误。
您的 WSGI 应用程序代码在构建重定向 URL 等时需要考虑在 WSGI 请求环境中传递的 SCRIPT_NAME
变量。参见:
通常 WSGI 框架会提供辅助函数来完成此操作。如果 Bottle 没有提供这样的功能,您需要自己实现。
如果您有单独的静态文件,您需要告诉 Apache 使用适当的 Alias
指令托管它们。
所以为了尝试这个,我从下面的 repo
中获取了样板代码
https://github.com/arsho/bottle-bootstrap
并以此为基础。我发现如果您遵循一些简单的规则
,则可以将您的应用程序安装在基础 url 上
- 您服务的每个 HTML 都应使用
HEAD
标记定义基本路径。喜欢<base href="{{ APP_MOUNT_PATH }}">
- 需要相对于基本路径的静态引用不应以
/
或./
开头。喜欢<script type="text/javascript" src="static/jquery.min.js"></script>
。这将确保使用您在 base
标签 中提供的安装路径生成路径
- 启动应用时从环境变量中获取挂载路径
这是更新后的文件
index.tpl
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Bottle web project template">
<meta name="author" content="datamate">
<link rel="icon" href="static/favicon.ico">
<base href="{{ APP_MOUNT_PATH }}">
<title>Project</title>
<link rel="stylesheet" type="text/css" href="static/bootstrap.min.css">
<script type="text/javascript" src="static/jquery.min.js"></script>
<script type="text/javascript" src="static/bootstrap.min.js"></script>
</head>
<body>
<!-- Static navbar -->
<nav class="navbar navbar-default navbar-static-top">
<div class="container">
<div class="row">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Project</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li><a href="navbar/">Home</a></li>
<li><a href="./">Github</a></li>
<li><a href="navbar-fixed-top/">Whosebug</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
</nav>
<div class="container">
<div class="row">
<div class="jumbotron">
<h2>Welcome from {{data["developer_name"]}}</h2>
<p>This is a template showcasing the optional theme stylesheet included in Bootstrap. Use it as a starting point to create something more unique by building on or modifying it.</p>
</div>
</div>
<!--./row-->
<div class="row">
<hr>
<footer>
<p>© 2017 {{data["developer_organization"]}}.</p>
</footer>
</div>
</div>
<!-- /container -->
</body>
</html>
app.py
from bottle import Bottle, run, \
template, debug, static_file
import os, sys
dirname = os.path.abspath(os.path.dirname(__file__))
app = Bottle()
debug(True)
@app.route('/static/<filename:re:.*\.css>')
def send_css(filename):
print("Sending", filename, dirname)
return static_file(filename, root=dirname+'/static/asset/css')
@app.route('/static/<filename:re:.*\.js>')
def send_js(filename):
print("Sending", filename, dirname)
return static_file(filename, root=dirname+'/static/asset/js')
@app.route('/')
def index():
data = {"developer_name":"Tarun Lalwani",
"developer_organization":""}
return template('index', data = data)
@app.route('/tarun/')
def tarun():
data = {"developer_name":"Tarun Lalwani",
"developer_organization":""}
return template('index', data = data)
if __name__ == "__main__":
run(app, host='localhost', port = 8080)
app.wsgi
import os
os.chdir(os.path.abspath(os.path.dirname(__file__)))
import bottle
from app import app
application = bottle.default_app()
mount_path = os.getenv("APP_MOUNT_PATH", "/")
application.config['APP_MOUNT_PATH'] = mount_path
application.mount(mount_path, app)
bottle.BaseTemplate.defaults['APP_MOUNT_PATH'] = mount_path
然后我 运行 使用 uwsgi
[uwsgi]
http = 127.0.0.1:3031
chdir = /Users/tarunlalwani/Documents/Projects/SO/bottle-bootstrap
pythonpath = .
env = APP_MOUNT_PATH=/app2/
wsgi-file = app.wsgi
processes = 1
threads = 1
stats = 127.0.0.1:9191
; logto = ./uwsgi.log
现在应用程序在 http://localhost:3031/app2/
和 ``http://localhost:3031/app2/tarun` 处加载正常,这表明基本路径适用于两种类型的 url
为了方便起见,所有代码都可以在下面的 repo 中找到
我使用 运行() 在本地开发了一个 Bottle 应用程序,根据教程所有路由都以“/”开头,现在我想将它放在真实服务器上。
http://bottlepy.org/docs/dev/deployment.html 的文档建议使用 WSGIScriptAlias / /var/www/yourapp/app.wsgi
,但我不希望 WSGI 应用程序处理我网站的根目录。我希望站点的根由原始 Apache 处理,只有 /app1 下的 URL 由 WSGI 处理。
所以我将我的设置为 WSGIScriptAlias /app1 /var/www/app1/app1.py
。它 运行 在某种意义上,当我浏览到 server://app1 时,我可以看到我在 route('/') 下的 .py 文件中定义的内容,但是 none 的超链接有 / app1 前置,浏览器无法从 /var/www/app1/css 等中获取我的 css 文件
主题说明了一切。当我希望应用程序位于子目录中时,是否必须在所有路由前添加“/app1”?
我试图让自己面向未来,因为我预见到将来会制作 /app2、/app3 等。
编辑 1:为了实验,我 did 尝试将 /app1 添加到所有路由。结果更糟:我尝试浏览 /app1 下的每个地址都会出现 404 错误。
您的 WSGI 应用程序代码在构建重定向 URL 等时需要考虑在 WSGI 请求环境中传递的 SCRIPT_NAME
变量。参见:
通常 WSGI 框架会提供辅助函数来完成此操作。如果 Bottle 没有提供这样的功能,您需要自己实现。
如果您有单独的静态文件,您需要告诉 Apache 使用适当的 Alias
指令托管它们。
所以为了尝试这个,我从下面的 repo
中获取了样板代码https://github.com/arsho/bottle-bootstrap
并以此为基础。我发现如果您遵循一些简单的规则
,则可以将您的应用程序安装在基础 url 上- 您服务的每个 HTML 都应使用
HEAD
标记定义基本路径。喜欢<base href="{{ APP_MOUNT_PATH }}">
- 需要相对于基本路径的静态引用不应以
/
或./
开头。喜欢<script type="text/javascript" src="static/jquery.min.js"></script>
。这将确保使用您在base
标签 中提供的安装路径生成路径
- 启动应用时从环境变量中获取挂载路径
这是更新后的文件
index.tpl
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Bottle web project template">
<meta name="author" content="datamate">
<link rel="icon" href="static/favicon.ico">
<base href="{{ APP_MOUNT_PATH }}">
<title>Project</title>
<link rel="stylesheet" type="text/css" href="static/bootstrap.min.css">
<script type="text/javascript" src="static/jquery.min.js"></script>
<script type="text/javascript" src="static/bootstrap.min.js"></script>
</head>
<body>
<!-- Static navbar -->
<nav class="navbar navbar-default navbar-static-top">
<div class="container">
<div class="row">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Project</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li><a href="navbar/">Home</a></li>
<li><a href="./">Github</a></li>
<li><a href="navbar-fixed-top/">Whosebug</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
</nav>
<div class="container">
<div class="row">
<div class="jumbotron">
<h2>Welcome from {{data["developer_name"]}}</h2>
<p>This is a template showcasing the optional theme stylesheet included in Bootstrap. Use it as a starting point to create something more unique by building on or modifying it.</p>
</div>
</div>
<!--./row-->
<div class="row">
<hr>
<footer>
<p>© 2017 {{data["developer_organization"]}}.</p>
</footer>
</div>
</div>
<!-- /container -->
</body>
</html>
app.py
from bottle import Bottle, run, \
template, debug, static_file
import os, sys
dirname = os.path.abspath(os.path.dirname(__file__))
app = Bottle()
debug(True)
@app.route('/static/<filename:re:.*\.css>')
def send_css(filename):
print("Sending", filename, dirname)
return static_file(filename, root=dirname+'/static/asset/css')
@app.route('/static/<filename:re:.*\.js>')
def send_js(filename):
print("Sending", filename, dirname)
return static_file(filename, root=dirname+'/static/asset/js')
@app.route('/')
def index():
data = {"developer_name":"Tarun Lalwani",
"developer_organization":""}
return template('index', data = data)
@app.route('/tarun/')
def tarun():
data = {"developer_name":"Tarun Lalwani",
"developer_organization":""}
return template('index', data = data)
if __name__ == "__main__":
run(app, host='localhost', port = 8080)
app.wsgi
import os
os.chdir(os.path.abspath(os.path.dirname(__file__)))
import bottle
from app import app
application = bottle.default_app()
mount_path = os.getenv("APP_MOUNT_PATH", "/")
application.config['APP_MOUNT_PATH'] = mount_path
application.mount(mount_path, app)
bottle.BaseTemplate.defaults['APP_MOUNT_PATH'] = mount_path
然后我 运行 使用 uwsgi
[uwsgi]
http = 127.0.0.1:3031
chdir = /Users/tarunlalwani/Documents/Projects/SO/bottle-bootstrap
pythonpath = .
env = APP_MOUNT_PATH=/app2/
wsgi-file = app.wsgi
processes = 1
threads = 1
stats = 127.0.0.1:9191
; logto = ./uwsgi.log
现在应用程序在 http://localhost:3031/app2/
和 ``http://localhost:3031/app2/tarun` 处加载正常,这表明基本路径适用于两种类型的 url
为了方便起见,所有代码都可以在下面的 repo 中找到