# To accept any number of query parameters, use Python's **data notation. # The keyword argument "data" will be a dictionary with all query parameters. # Images, CSS, etc. can be placed in the static folder. # Take a look in /01-basic/static. There's a "cat.jpg". # Static files are accessible from the web, e.g., # http://127.0.0.1:8080/cat.jpg # So, you can refer to them in HTML code: # http://127.0.0.1:8080/cat @app.route("/cat") def cat(): return "<p>A cat.</p><img src='cat.jpg'>" # http://127.0.0.1:8080/cat-alias.jpg @app.route("/cat-alias.jpg") def cat_alias(): return static("cat.jpg", root=app.static) # That's it. There is lot more you can do, but the general idea is: # 1) Create an App. # 2) Register URL handlers with @app.route(). # 3) Start the server with app.run(). app.run("127.0.0.1", port=8080, debug=True)
# It creates an optional parameter "db" that is available in every URL handler, # and which contains a connection to the database for the active thread. @app.bind("db") def db(): return Database(STORE) # Note how the path handler for http://127.0.0.1:8080/products # takes the optional parameter "db". # For http://127.0.0.1:8080/products, it displays an overview of all products. # For http://127.0.0.1:8080/products/rubber-chicken, it displays the product with the given name. # The html.table() helper function returns a HTML-string with a <table> element. @app.route("/products") def products(name, db=None): if name is None: sql, v = "select * from `products`", () else: sql, v = "select * from `products` where name=?", (name.replace( "-", " "), ) rows = db.execute(sql, values=v) rows = [(row.id, row.name, row.price) for row in rows] return html.table(rows, headers=("id", "name", "price")) app.run("127.0.0.1", 8080, threads=30, queue=20)
"<textarea name='text'></textarea>", "<br><input type='submit'>", "</form>" ) # To accept any number of query parameters, use Python's **data notation. # The keyword argument "data" will be a dictionary with all query parameters. # Images, CSS, etc. can be placed in the static folder. # Take a look in /01-basic/static. There's a "cat.jpg". # Static files are accessible from the web, e.g., # http://127.0.0.1:8080/cat.jpg # So, you can refer to them in HTML code: # http://127.0.0.1:8080/cat @app.route("/cat") def cat(): return "<p>A cat.</p><img src='cat.jpg'>" # http://127.0.0.1:8080/cat-alias.jpg @app.route("/cat-alias.jpg") def cat_alias(): return static("cat.jpg", root=app.static) # That's it. There is lot more you can do, but the general idea is: # 1) Create an App. # 2) Register URL handlers with @app.route(). # 3) Start the server with app.run(). app.run("127.0.0.1", port=8080, debug=True)
# Because the server is multi-threaded, # each separate thread needs its own Database object. # This is handled for us by using @app.bind(). # It creates an optional parameter "db" that is available in every URL handler, # and which contains a connection to the database for the active thread. @app.bind("db") def db(): return Database(STORE) # Note how the path handler for http://127.0.0.1:8080/products # takes the optional parameter "db". # For http://127.0.0.1:8080/products, it displays an overview of all products. # For http://127.0.0.1:8080/products/rubber-chicken, it displays the product with the given name. # The html.table() helper function returns a HTML-string with a <table> element. @app.route("/products") def products(name, db=None): if name is None: sql, v = "select * from `products`", () else: sql, v = "select * from `products` where name=?", (name.replace("-", " "),) rows = db.execute(sql, values=v) rows = [(row.id, row.name, row.price) for row in rows] return html.table(rows, headers=("id", "name", "price")) app.run("127.0.0.1", 8080, threads=30, queue=20)
# In this case, only the user with key=1234 is allowed access. # All other requests will generate a HTTP 403 Forbidden error. # A user can pass his personal key as a query parameter, e.g., # http://127.0.0.1:8080/language/paid?q=hello&key=1234 # Check personal keys instead of IP-address: @app.route("/language/paid", limit=True, key=lambda data: data.get("key")) def predict_language_paid(q="", key=None): return {"language": language(q)[0]} # Create an account for user with key=1234 (do once). # You can generate fairly safe keys with app.rate.key(). if not app.rate.get(key="1234", path="/language/paid"): app.rate.set(key="1234", path="/language/paid", limit=10000, time=DAY) # Try it out with the key and without the key: # http://127.0.0.1:8080/language/paid?q=hello&key=1234 # http://127.0.0.1:8080/language/paid?q=hello (403 error) # A rate.db SQLite database was created in the current folder. # If you want to give it another name, use App(rate="xxx.db"). # To view the contents of the database,we use the free # SQLite Database Browser (http://sqlitebrowser.sourceforge.net). # If the web service is heavily used, # we may want to use more threads for concurrent requests # (default is 30 threads with max 20 queueing): app.run("127.0.0.1", port=8080, threads=100, queue=50)
# posting the data inside the <textarea> to the server. # We can catch it as the optional "content" parameter of the index() function # (since the name of the <textarea> is "content"). def edit(page): s = open(page).read() if os.path.exists(page) else "" s = '<form method="post" action="?save">' \ '<textarea name="content" rows="10" cols="80">%s</textarea><br>' \ '<input type="submit">' \ '</form>' % s return template(wiki, name=name(page), content=s) # The save() function is called when edited content is posted to the server. # It creates a file in /data and stores the content. @threadsafe def save(page, src): f = open(page, "w") f.write(src.encode("utf-8")) f.close() return view(page) # Writing HTML by hand in the <textarea> becomes tedious after a while, # so we could for example extend save() with a parser for Markdown syntax: # http://en.wikipedia.org/wiki/Markdown, # http://pythonhosted.org/Markdown/, # or replace the <textarea> with a visual TinyMCE editor: # http://www.tinymce.com. app.run("127.0.0.1", port=8080)
# All other requests will generate a HTTP 403 Forbidden error. # A user can pass his personal key as a query parameter, e.g., # http://127.0.0.1:8080/language/paid?q=hello&key=1234 # Check personal keys instead of IP-address: @app.route("/language/paid", limit=True, key=lambda data: data.get("key")) def predict_language_paid(q="", key=None): return {"language": language(q)[0]} # Create an account for user with key=1234 (do once). # You can generate fairly safe keys with app.rate.key(). if not app.rate.get(key="1234", path="/language/paid"): app.rate.set(key="1234", path="/language/paid", limit=10000, time=DAY) # Try it out with the key and without the key: # http://127.0.0.1:8080/language/paid?q=hello&key=1234 # http://127.0.0.1:8080/language/paid?q=hello (403 error) # A rate.db SQLite database was created in the current folder. # If you want to give it another name, use App(rate="xxx.db"). # To view the contents of the database,we use the free # SQLite Database Browser (http://sqlitebrowser.sourceforge.net). # If the web service is heavily used, # we may want to use more threads for concurrent requests # (default is 30 threads with max 20 queueing): app.run("127.0.0.1", port=8080, threads=100, queue=50)