Как загрузить файл javascript или css в шаблон BottlePy?
Я пытаюсь вернуть html-шаблон с помощью BottlePy. И это прекрасно работает. Но если я вложу такой файл javascript в мой tpl файл:
<script type="text/javascript" src="js/main.js" charset="utf-8"></script>
Я получаю ошибку 404.
(Не удалось загрузить ресурс: сервер ответил статусом 404 (не найден))
Кто-нибудь знает, как решить эту проблему?
Вот мой файл script:
from bottle import route, run, view
@route('/')
@view('index')
def index():
return dict()
run(host='localhost', port=8080)
И это файл шаблона, расположенный в подпапке "./views".
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8" />
<script type="text/javascript" src="js/main.js" charset="utf-8"></script>
</head>
<body>
</body>
</html>
Может быть, это "rootPath/js/main.js" с сервера разработки, где он ищет мой js файл?
Структура файлов:
app.py
-js
main.js
-views
index.tpl
Спасибо.
Ответы
Ответ 1
Ну, во-первых, вам нужен ваш сервер-разработчик, чтобы фактически обслуживать main.js
, иначе он не будет доступен для браузера.
Обычно для размещения всех файлов .js
и .css
в каталоге static
в небольших веб-приложениях, ваш макет должен выглядеть следующим образом:
app.py
- static/
main.js
- views/
index.tpl
Ни в коем случае это точное именование и макет не требуется, только часто используется.
Затем вы должны предоставить обработчик для статических файлов:
from bottle import static_file
# ...
@route('/static/:path#.+#', name='static')
def static(path):
return static_file(path, root='static')
Это приведет к тому, что ваши файлы в static/
будут отображаться в браузере.
Теперь, к последней вещи. Вы указали свой JavaScript как:
<script type="text/javascript" src="js/main.js" charset="utf-8"></script>
Это означает, что путь к .js
относится к текущей странице. На вашем сервере разработки индексная страница (/
) будет искать .js
в /js/main.js
, а другая страница (скажем, /post/12
) будет искать ее в /post/12/js/main.js
и обязательно не удастся.
Вместо этого вам нужно использовать функцию get_url
для правильной ссылки на статические файлы. Ваш обработчик должен выглядеть следующим образом:
from Bottle import get_url
# ...
@route('/')
@view('index')
def index():
return { 'get_url': get_url }
И в index.tpl
, .js
следует ссылаться как:
<script type="text/javascript" src="{{ get_url('static', path='main.js') }}" charset="utf-8"></script>
get_url
находит обработчик с name='static'
и вычисляет правильный путь к нему. Для dev-сервера это всегда будет /static/
. Возможно, вы даже можете его жестко закодировать в шаблоне, но я не рекомендую его по двум причинам:
- Вы не сможете монтировать свое приложение нигде, но под управлением root; т.е. когда вы загружаете его на сервер porduction, его можно поместить под http://example.com/ (root), но не под http://example.com/myapp/.
- Если вы измените расположение каталога
/static/
, вам придется искать его по всем вашим шаблонам и изменять его в каждом отдельном шаблоне.
Ответ 2
Я думаю, что вы помещаете файл main.js
в неправильное расположение.
Обратите внимание, что этот путь к файлу должен быть относительно запрошенного URL-адреса, а не по отношению к пути к вашему шаблону. Поэтому размещение его в папке типа template/js/main.js
не будет работать.
Ответ 3
Вот рабочий подход добавления статических файлов, таких как CSS/JS, в веб-проекте Бутылка. Я использую Bootstrap и Python 3.6.
Структура проекта
project
│ app.py
│ bottle.py
│
├───static
│ └───asset
│ ├───css
│ │ bootstrap-theme.css
│ │ bootstrap-theme.css.map
│ │ bootstrap-theme.min.css
│ │ bootstrap-theme.min.css.map
│ │ bootstrap.css
│ │ bootstrap.css.map
│ │ bootstrap.min.css
│ │ bootstrap.min.css.map
│ │ custom.css
│ │
│ ├───fonts
│ │ glyphicons-halflings-regular.eot
│ │ glyphicons-halflings-regular.svg
│ │ glyphicons-halflings-regular.ttf
│ │ glyphicons-halflings-regular.woff
│ │ glyphicons-halflings-regular.woff2
│ │
│ └───js
│ bootstrap.js
│ bootstrap.min.js
│ jquery.min.js
│ npm.js
│
└───views
index.tpl
app.py
from bottle import Bottle, run, \
template, debug, static_file
import os, sys
dirname = os.path.dirname(sys.argv[0])
app = Bottle()
debug(True)
@app.route('/static/<filename:re:.*\.css>')
def send_css(filename):
return static_file(filename, root=dirname+'/static/asset/css')
@app.route('/static/<filename:re:.*\.js>')
def send_js(filename):
return static_file(filename, root=dirname+'/static/asset/js')
@app.route('/')
def index():
data = {"developer_name":"Ahmedur Rahman Shovon",
"developer_organization":"Datamate Web Solutions"}
return template('index', data = data)
run(app, host='localhost', port = 8080)
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">
<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/">Stackoverflow</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>
Выход
![демонстрация бутылочной бутстрапа]()