You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
90 lines
3.6 KiB
Python
90 lines
3.6 KiB
Python
from __future__ import print_function
|
|
from __future__ import unicode_literals
|
|
|
|
from builtins import str, bytes, dict, int
|
|
|
|
import os
|
|
import sys
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", ".."))
|
|
|
|
from pattern.server import App, Database, html
|
|
|
|
# This example demonstrates a web app with a simple database back-end.
|
|
# The pattern.server module has a Database object
|
|
# that can be used with SQLite and MySQL databases.
|
|
# SQLite is part of Python 2.5+.
|
|
# MySQL requires the mysql-python bindings (http://sourceforge.net/projects/mysql-python/).
|
|
|
|
app = App("store")
|
|
|
|
# In this example we'll use SQLite.
|
|
# The advantage is that you don't need to install anything,
|
|
# and that the database is a file at a location of your choice.
|
|
# We use SQLite Database browser (Mac OS X) to browse the file.
|
|
# (http://sourceforge.net/projects/sqlitebrowser/)
|
|
|
|
# The disadvantage is that SQLite is not multi-threaded.
|
|
# This will lead to problems ("database is locked") in larger projects.
|
|
# The app server uses multiple threads to handle concurrent requests.
|
|
# If two request want to write to the database at the same time,
|
|
# one of them will have to wait while the other finishes writing.
|
|
# If enough requests are waiting in line, the database may crash.
|
|
# The next example uses a DatabaseTransaction to remedy this.
|
|
# Reading from the database is no problem.
|
|
|
|
# The following code creates a new database "store.db",
|
|
# in the same folder as this script.
|
|
# Databases can be queried and modified with SQL statements.
|
|
# The SQL code below creates a "products" table in the database.
|
|
# Each table has fields (or columns) with a type (text, int, float, ...).
|
|
|
|
STORE = os.path.join(os.path.dirname(__file__), "store.db")
|
|
|
|
if not os.path.exists(STORE):
|
|
db = Database(STORE, schema="""
|
|
create table if not exists `products` (
|
|
`id` integer primary key autoincrement,
|
|
`name` text,
|
|
`price` float
|
|
);
|
|
create index if not exists products_name on products(name);
|
|
"""
|
|
)
|
|
# Add some rows of data to the "products" table:
|
|
db.execute("insert into `products` (name, price) values (?, ?)", values=("rubber chicken", "199"), commit=False)
|
|
db.execute("insert into `products` (name, price) values (?, ?)", values=("donkey costume", "249"), commit=False)
|
|
db.execute("insert into `products` (name, price) values (?, ?)", values=("mysterious box", "999"), commit=False)
|
|
db.commit()
|
|
|
|
# The most interesting part in this example is the code below.
|
|
# 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)
|