I'm working on a python app in Python Bottle. The app works fine if I'm on 1 lvl deep URLs like /dashboard or /rules or /page. However, if I go deeper like /dashboard/overview or /rules/ruleone or /page/test the CSS, JS, fonts and images will fail. :(
The HTML source code still poinsts to /assets/ but if I'm on an URL like /rules/ruleone, the right path should be something like ../assets or ./assets right? The path /assets/ only works on the first level but not on deeper lvls, in other words: bottle doesnt adapt the static file path to the current directory. How do I fix this?
I'm stuck on this problem for days now, I realy hope someone can help me. :(
My code (simplified):
#!/usr/bin/env python
import lib.bottle as bottle
from lib.bottle import route, template, debug, static_file, TEMPLATE_PATH, error, auth_basic, get, post, request, response, run, view, redirect, SimpleTemplate, HTTPError, abort
import os, sys, re
#route('/dashboard')
#view('secure_page')
def show__page_dashboard():
return dict(page = 'Dashboard')
#route('/rules/<rule>')
#view('secure_page')
def show_page_rules_more(rule):
return dict(page = rule)
#route('/assets/<filepath:path>')
def server_static(filepath):
return static_file(filepath, root='/var/myapp/assets')
TEMPLATE_PATH.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "view")))
bottle.debug(True)
from lib.bottledaemon import daemon_run
if __name__ == "__main__":
daemon_run()
So my app runs in daemon mode. The structure is:
lib
bottle.py
bottledaemon.py
assets
css
js
...
view
secure_page.tpl
footer.tpl
header.tpl
...
server.py
I hope someone can help me out on this, thanks in advance guys, I love u! <3
Alright I found the solution for my problem. Bottle offers an URL tag to dynamicly build URLs.
from bottle import url
#route('/dashboard')
#view('secure_page')
def show__page_dashboard():
return dict(page='Dashboard', url=url)
#route('/assets/<filepath:path>', name='assets')
def server_static(filepath):
return static_file(filepath, root='/var/myapp/assets')
This is how I load my CSS/JS/images
<link href="{{ url('assets', filepath='css/style.css') }}" rel="stylesheet" type="text/css"/>
Dynamic menu URL's (in the navigation for example) is done this way:
{{ url('/dashboard') }}
I hope this info will help someone who is strugling with the same problem as I was.
Tested on v0.12 and v0.13dev
I do use:
#route('/css/<filename>')
def stylesheets(filename):
return static_file(filename, root='./static/css/')
and in template use:
<link href="/css/style.css" rel="stylesheet">
can be replicated for all assets items (img, css, and js)
Related
My picture isnt showing, I tryed copying code and that didnt work. I want to be able to do this, what am i doing wrong?
my code
from bottle import route, run,Response,template
from bottle import *
import socket
temp=open("ht","r")
html1=temp.read()
temp=open("html2","r")
html2=temp.read()
#route("/")
def route1():
return html1
run(host=socket.gethostbyname(socket.gethostname()), port=8080, debug=True)
in html1
<img src="C:\Users\radbo\Desktop\discord bots\drago\chat\RUn\Servers\Turtle.png" width=290 length=100>
Use the template function to call your HTML so it is cached, then create a static path to your image file.
from bottle import route, run, response, request, template, static_file, get
#route("/")
def route1():
#this should be your full filename, like index.html
return template('ht')
#get('/static/<filepath:path>')
def _shared(filepath):
return static_file(filepath, 'C:\Users\radbo\Desktop\discord bots\drago\chat\RUn\Servers' )
run(host='127.0.0.1', port=8080, debug=True)
Then you can just do:
<img src="\static\Turtle.png" width=290 length=100>
I'm using apidoc to generate a documentation website. On running, it creates a folder called doc, which contains an index.html file and accompanying css and js.
I'd like to be able to serve this folder with a Flask server, but can't work out how to do it.
My folder structure looks like this
-root
--- doc/ #contains all of the static stuff
--- server.py
I've tried this, but can't get it to work:
app = Flask(__name__, static_url_path="/doc")
#app.route('/')
def root():
return app.send_from_directory('index.html')
One of the problems is that all of the static files referenced in the index.html generated by apidoc are relative to that page, so /js/etc. doesn't work, since it's actually /doc/js...
It would be great if someone could help me with the syntax here. Thanks.
I spot three problems in code.
a) you do not need to use static_url_path, as send_from_directory is independent of it
b) when I try to run above code, and go to /, I get a AttributeError: 'Flask' object has no attribute 'send_from_directory' - this means translates to app.send_from_directory is wrong - you need to import this function from flask, ie from flask import send_from_directory
c) when I then try to run your code, I get a TypeError: send_from_directory() missing 1 required positional argument: 'filename', which means send_from_directory needs another argument; it needs both a directory and a file
Putting this all together you get something like this:
from flask import Flask
from flask import send_from_directory
app = Flask(__name__)
#app.route("/")
def index():
return send_from_directory("doc", "index.html")
As a takeway (for myself):
reading the documentation helps a lot ( https://flask.palletsprojects.com/en/1.1.x/api/ )
having a close look at the - at first scary - error messages gives really good hints on what to do
So I have two domains:
MAIN_DOMAIN = www.example.com
DUTCH_DOMAIN = www.voorbeeld.com
I want to use the dutch domain with Flask-Babel for i18n support.
To make this possible I'm using host_matching like this:
def create_app(config_class=Config):
app = Flask(__name__, host_matching=True,
static_host=MAIN_DOMAIN)
Finally, routing:
#bp.route('/', host=MAIN_DOMAIN)
#bp.route('/', host=DUTCH_DOMAIN)
def index():
return render_template('index.html')
I might want to change the routing part in the future. But for now this works fine.
Now for the problem, when I navigate to the dutch domain everything works, except that I get many 404 error messages because it can't find the static files. If I change the url of the static files to the MAIN_DOMAIN it works fine. Which makes sense since static_host is set to MAIN_DOMAIN.
So I just can't seem to find a solution for this problem. Is there a way to make both domains for static files work? Or how would you solve this?
Ok. So I've figured it out and actually noticed some interesting behaviour.
So when I go to the main domain. url_for works as expected, so if you would do something like this in your templates:
<script src="{{ url_for('static', filename='jquery/dist/jquery.min.js') }}"></script>
The result would be this:
<script src="/static/jquery/dist/jquery.min.js"></script>
However, when I go to the DUTCH_DOMAIN route I get:
<script src="http://www.example.com/static/jquery/dist/jquery.min.js"></script>
So you don't have to manually add _external=True to url_for for you other domains but it all happens automagically. The reason it didn't work before is because of CORS since from the browser point of view you're loading assets from a different domain instead of from the "local" website.
Hope this helps.
I'm trying to use a boilerplate I downloaded from Initializr together with bottle.py. I'm obviously doing something wrong since when I simply try to load index.html the site renders without using any of the stylesheets and I get the following errors in the browser console:
Use of getUserData() or setUserData() is deprecated. Use WeakMap or element.dataset instead. requestNotifier.js:52
The stylesheet http://localhost:8080/css/normalize.min.css was not loaded because its MIME type, "text/html", is not "text/css". localhost:8080
The stylesheet http://localhost:8080/css/main.css was not loaded because its MIME type, "text/html", is not "text/css". localhost:8080
SyntaxError: syntax error modernizr-2.6.2-respond-1.1.0.min.js:1
SyntaxError: syntax error plugins.js:1
SyntaxError: syntax error
My app looks like this:
import bottle # Web server
from bottle import run, route, static_file, error, template # import request
#route('/')
def index():
return static_file('index.html', root='./html/')
#route('./css/<filename>')
def server__static(filename):
return static_file(filename, root='./css/')
if __name__ == '__main__':
# To run the server, type-in $ python server.py
bottle.debug(True) # display traceback
run(host='localhost', port=8080, reloader=True)
The stylesheets are called from index.html like so:
<link type="text/css" rel="stylesheet" href="css/normalize.min.css">
<link type="text/css" rel="stylesheet" href="css/main.css">
My basic folder structure is (snipped js folder etc.):
bottle_test.py
- html
index.html
- css
main.css
normalize.min.css
I understand that bottle doesn't serve static files by itself and I did play around with the route to server-static and added, changed and removed the mimetype argument but can't get it to work.
The entire boilerplate sits in the html folder and the app does find index.html. I tried this in Firefox and Chrome. I'm on Win 8.1 and anaconda's python 2.7 if that matters. What am I doing wrong?
Your paths seem wrong. The CSS route shouldn't start with a ., seems it interferes with how Bottle parses it. And your CSS static_file root doesn't properly reflect the css folder placement relative to the working directory.
This should work alright:
#route('/css/<filename>')
def server__static(filename):
return static_file(filename, root='./html/css')
I'm very new to Python. I just know what Python is.
I have created the below code (in Python IDLE):
print "Hi Welcome to Python test page\n";
print "Now it will show a calculation";
print "30+2=";
print 30+2;
Then I saved this page in my localhost as index.py
I run the script using
http://localhost/index.py
But it does not show the executed Python script. Instead, it showed the above code as HTML. Where is the problem? How can I run a Python file in a web page?
In order for your code to show, you need several things:
Firstly, there needs to be a server that handles HTTP requests. At the moment you are just opening a file with Firefox on your local hard drive. A server like Apache or something similar is required.
Secondly, presuming that you now have a server that serves the files, you will also need something that interprets the code as Python code for the server. For Python users the go to solution is nowadays mod_wsgi. But for simpler cases you could stick with CGI (more info here), but if you want to produce web pages easily, you should go with a existing Python web framework like Django.
Setting this up can be quite the hassle, so be prepared.
As others have pointed out, there are many web frameworks for Python.
But, seeing as you are just getting started with Python, a simple CGI script might be more appropriate:
Rename your script to index.cgi. You also need to execute chmod +x index.cgi to give it execution privileges.
Add these 2 lines in the beginning of the file:
#!/usr/bin/python
print('Content-type: text/html\r\n\r')
After this the Python code should run just like in terminal, except the output goes to the browser. When you get that working, you can use the cgi module to get data back from the browser.
Note: this assumes that your webserver is running Linux. For Windows, #!/Python26/python might work instead.
Using the Flask library in Python, you can achieve that.
Remember to store your HTML page to a folder named "templates" inside where you are running your Python script.
So your folder would look like
templates (folder which would contain your HTML file)
your Python script
This is a small example of your Python script. This simply checks for plagiarism.
from flask import Flask
from flask import request
from flask import render_template
import stringComparison
app = Flask(__name__)
#app.route('/')
def my_form():
return render_template("my-form.html") # This should be the name of your HTML file
#app.route('/', methods=['POST'])
def my_form_post():
text1 = request.form['text1']
text2 = request.form['text2']
plagiarismPercent = stringComparison.extremelySimplePlagiarismChecker(text1,text2)
if plagiarismPercent > 50 :
return "<h1>Plagiarism Detected !</h1>"
else :
return "<h1>No Plagiarism Detected !</h1>"
if __name__ == '__main__':
app.run()
This a small template of HTML file that is used:
<!DOCTYPE html>
<html lang="en">
<body>
<h1>Enter the texts to be compared</h1>
<form action="." method="POST">
<input type="text" name="text1">
<input type="text" name="text2">
<input type="submit" name="my-form" value="Check !">
</form>
</body>
</html>
This is a small little way through which you can achieve a simple task of comparing two strings and which can be easily changed to suit your requirements.
If you are using your own computer, install a software called XAMPP (or WAMP either works). This is basically a website server that only runs on your computer. Then, once it is installed, go to the xampp folder and double click the htdocs folder. Now you
need to create an HTML file (I'm going to call it runpython.html). (Remember to move the Python file to htdocs as well.)
Add in this to your HTML body (and inputs as necessary).
<form action = "file_name.py" method = "POST">
<input type = "submit" value = "Run the Program!!!">
</form>
Now, in the Python file, we are basically going to be printing out HTML code.
# We will need a comment here depending on your server. It is basically telling the server where your python.exe is in order to interpret the language. The server is too lazy to do it itself.
import cgitb
import cgi
cgitb.enable() # This will show any errors on your webpage
inputs = cgi.FieldStorage() # REMEMBER: We do not have inputs, simply a button to run the program. In order to get inputs, give each one a name and call it by inputs['insert_name']
print "Content-type: text/html" # We are using HTML, so we need to tell the server
print # Just do it because it is in the tutorial :P
print "<title> MyPythonWebpage </title>"
print "Whatever you would like to print goes here, preferably in between tags to make it look nice"
Well, the OP didn't say server or client side, so I will just leave this here in case someone like me is looking for client side:
Skulpt is a implementation of Python to run at client side. Very interesting, no plugin required, just simple JavaScript code.
With your current requirement, this would work:
def start_html():
return '<html>'
def end_html():
return '</html>'
def print_html(text):
text = str(text)
text = text.replace('\n', '<br>')
return '<p>' + str(text) + '</p>'
if __name__ == '__main__':
webpage_data = start_html()
webpage_data += print_html("Hi Welcome to Python test page\n")
webpage_data += fd.write(print_html("Now it will show a calculation"))
webpage_data += print_html("30+2=")
webpage_data += print_html(30+2)
webpage_data += end_html()
with open('index.html', 'w') as fd: fd.write(webpage_data)
Open the index.html file, and you will see what you want.