- Linux and Unix
- One step production deployment
- Apache setup
- mod_wsgi
- Setting password
- mod_wsgi and SSL
- mod_proxy
- Start as Linux daemon
- Nginx
- Lighttpd
- Shared hosting with mod_python
- Cherokee with FastCGI
- Postgresql
- Start the scheduler as a Linux service (upstart)
- Initial Queuing of a Repeating Task
- Populating a Database on Deployment
Linux and Unix
One step production deployment
Here are some steps to install apache+python+mod_wsgi+web2py+postgresql from scratch.
On Ubuntu:
wget https://raw.githubusercontent.com/web2py/web2py/master/scripts/setup-web2py-ubuntu.sh
chmod +x setup-web2py-ubuntu.sh
sudo ./setup-web2py-ubuntu.sh
On Fedora:
wget https://raw.githubusercontent.com/web2py/web2py/master/scripts/setup-web2py-fedora.sh
chmod +x setup-web2py-fedora.sh
sudo ./setup-web2py-fedora.sh
Both of these scripts should run out of the box, but every Linux installation is a bit different, so make sure you check the source code of these scripts before you run them. In the case of Ubuntu, most of what they do is explained below. They do not implement the scalability optimizations discussed below.
Apache setup
In this section, we use Ubuntu Server Edition as the reference platform. The configuration commands are very similar on other Debian-based Linux distribution, but they may differ for Fedora-based systems (which uses yum
instead of apt-get
). You can use either 2.2.x or 2.4.x
First, make sure all the necessary Python and Apache packages are installed by typing the following shell commands:
sudo apt-get update
sudo apt-get -y upgrade
sudo apt-get -y install openssh-server
sudo apt-get -y install python
sudo apt-get -y install python-dev
sudo apt-get -y install apache2
sudo apt-get -y install libapache2-mod-wsgi
sudo apt-get -y install libapache2-mod-proxy-html
Then, enable the SSL module, the proxy module, and the WSGI module in Apache:
sudo ln -s /etc/apache2/mods-available/proxy_http.load /etc/apache2/mods-enabled/proxy_http.load
sudo a2enmod ssl
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod wsgi
Create the SSL folder, and put the SSL certificates inside it:
sudo mkdir /etc/apache2/ssl
You should obtain your SSL certificates from a trusted Certificate Authority such as verisign.com, but, for testing purposes, you can generate your own self-signed certificates following the instructions in ref.[openssl]
Then restart the web server:
sudo /etc/init.d/apache2 restart
The Apache configuration file is:
/etc/apache2/sites-available/default
The Apache logs are in:
/var/log/apache2/
mod_wsgi
Download and unzip web2py source on the machine where you installed the web server above.
Install web2py under /home/www-data/
, for example, and give ownership to user www-data and group www-data. These steps can be performed with the following shell commands:
cd /home/www-data/
sudo wget http://web2py.com/examples/static/web2py_src.zip
sudo unzip web2py_src.zip
sudo chown -R www-data:www-data /home/www-data/web2py
To set up web2py with mod_wsgi, create a new Apache configuration file:
/etc/apache2/sites-available/web2py
and include the following code:
<VirtualHost *:80>
ServerName web2py.example.com
WSGIDaemonProcess web2py user=www-data group=www-data display-name=%{GROUP}
WSGIProcessGroup web2py
WSGIScriptAlias / /home/www-data/web2py/wsgihandler.py
#This is Apache 2.2.x permission syntax. See Apache docs for 2.4 syntax
# http://httpd.apache.org/docs/2.4/upgrading.html#run-time
<Directory /home/www-data/web2py>
AllowOverride None
Order Allow,Deny
Deny from all
<Files wsgihandler.py>
Allow from all
</Files>
</Directory>
AliasMatch ^/([^/]+)/static/(?:_[\d]+.[\d]+.[\d]+/)?(.*) /home/www-data/web2py/applications/$1/static/$2
<Directory /home/www-data/web2py/applications/*/static/>
Order Allow,Deny
Allow from all
</Directory>
<Location /admin>
Deny from all
</Location>
<LocationMatch ^/([^/]+)/appadmin>
Deny from all
</LocationMatch>
CustomLog /private/var/log/apache2/access.log common
ErrorLog /private/var/log/apache2/error.log
</VirtualHost>
When you restart Apache, it should pass all the requests to web2py without going through the Rocket wsgiserver.
Move the handler script
Finally, you need to relocate the handler script web2py/handlers/wsgihandler.py
. As documented in the handlers directory, the script you want should be moved or copied to the parent directory (i.e. the same directory as the web2py.py
script). symlinking may cause apache permission problems.
Some wsgi background
Here are some explanations:
WSGIDaemonProcess web2py user=www-data group=www-data display-name=%{GROUP}
defines a daemon process group in context of “web2py.example.com”. By defining this inside of the virtual host, only this virtual host can access this using WSGIProcessGroup, including any virtual host with the same server name but on a different port. The “user” and “group” options should be set to the user who has write access to the directory where web2py was setup. You do not need to set “user” and “group” if you made the web2py installation directory writable by the default user that Apache runs as. The “display-name” option makes the process name appears in ps
output as “(wsgi-web2py)” instead of as name of Apache web server executable. As no “processes” or “threads” options are specified, the daemon process group will have a single process with 15 threads running within that process. This is usually more than adequate for most sites and should be left as is. If overriding it, do not use “processes=1” as doing so will disable any in-browser WSGI debugging tools that check the “wsgi.multiprocess” flag. This is because any use of the “processes” option will cause that flag to be set to true, even a single process, and such tools expect that it be set to false. Note: if your application code or third party extension module is not thread safe, use options “processes=5 threads=1” instead. This will create five processes in the daemon process group where each process is single threaded. You might consider using “maximum-requests=1000” if your application leaks Python objects because it is unable to garbage collect properly.
WSGIProcessGroup web2py
delegates running of all WSGI applications to the daemon process group that was configured using the WSGIDaemonProcess directive.
WSGIScriptAlias / /home/www-data/web2py/wsgihandler.py
mounts the web2py application. In this case it is mounted at the root of the web site.
<Directory /home/www-data/web2py>
...
</Directory>
gives Apache permission to access the WSGI script file.
<Directory /home/www-data/web2py/applications/*/static/>
Order Allow,Deny
Allow from all
</Directory>
Instructs Apache to bypass web2py when searching static files.
<Location /admin>
Deny from all
</Location>
and
<LocationMatch ^/([^/]+)/appadmin>
Deny from all
</LocationMatch>
blocks public access to admin and appadmin
Normally we would just allow permission to the whole directory where the WSGI script file is located, but web2py places the WSGI script file in a directory which contains other source code, including the admin interface password. Opening up the whole directory would cause security issues, because technically Apache would be given permission to serve all the files up to any user who traversed to that directory via a mapped URL. To avoid security problems, explicitly deny access to the contents of the directory, except for the WSGI script file, and prohibit a user from doing any overrides from a .htaccess file to be extra safe.
You can find a completed, commented, Apache wsgi configuration file in:
scripts/web2py-wsgi.conf
This section was created with help from Graham Dumpleton, developer of mod_wsgi.
Setting password
In production it may be necessary to set the admin password programmatically. This can be done from the Bash shell with
sudo -u www-data python -c "from gluon.main import save_password; save_password(raw_input('admin password: '), 443)"
mod_wsgi and SSL
To force some applications (for example admin and appadmin) to go over HTTPS, store the SSL certificate and key files:
/etc/apache2/ssl/server.crt
/etc/apache2/ssl/server.key
and edit the Apache configuration file web2py.conf
and append:
<VirtualHost *:443>
ServerName web2py.example.com
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/server.crt
SSLCertificateKeyFile /etc/apache2/ssl/server.key
WSGIProcessGroup web2py
WSGIScriptAlias / /home/www-data/web2py/wsgihandler.py
<Directory /home/www-data/web2py>
AllowOverride None
Order Allow,Deny
Deny from all
<Files wsgihandler.py>
Allow from all
</Files>
</Directory>
AliasMatch ^/([^/]+)/static/(?:_[\d]+.[\d]+.[\d]+/)?(.*) /home/www-data/web2py/applications/$1/static/$2
<Directory /home/www-data/web2py/applications/*/static/>
Order Allow,Deny
Allow from all
</Directory>
CustomLog /private/var/log/apache2/access.log common
ErrorLog /private/var/log/apache2/error.log
</VirtualHost>
Restart Apache and you should be able to access:
https://www.example.com/admin
https://www.example.com/examples/appadmin
http://www.example.com/examples
but not:
http://www.example.com/admin
http://www.example.com/examples/appadmin
mod_proxy
Some Unix/Linux distributions can run Apache, but do not support mod_wsgi. In this case, the simplest solution is to run Apache as a proxy and have Apache deal with static files only.
Here is a minimal Apache configuration:
NameVirtualHost *:80
#### deal with requests on port 80
<VirtualHost *:80>
Alias / /home/www-data/web2py/applications
### serve static files directly
<LocationMatch "^/welcome/static/.*">
Order Allow, Deny
Allow from all
</LocationMatch>
### proxy all the other requests
<Location "/welcome">
Order deny,allow
Allow from all
ProxyRequests off
ProxyPass http://localhost:8000/welcome
ProxyPassReverse http://localhost:8000/
ProxyHTMLURLMap http://127.0.0.1:8000/welcome/ /welcome
</Location>
LogFormat "%h %l %u %t "%r" %>s %b" common
CustomLog /var/log/apache2/access.log common
</VirtualHost>
The above script exposes only the “welcome” application. To expose other applications, you need to add the corresponding
The script assumes there is a web2py server running on port 8000. Before restarting Apache, make sure this is the case:
nohup python web2py.py -a '<recycle>' -i 127.0.0.1 -p 8000 &
You can specify a password with the -a
option or use the “
You can also use the parameter “
The nohup
commands makes sure the server does not die when you close the shell. nohup
logs all output into nohup.out
.
To force admin and appadmin over HTTPS use the following Apache configuration file instead:
NameVirtualHost *:80
NameVirtualHost *:443
#### deal with requests on port 80
<VirtualHost *:80>
Alias / /home/www-data/web2py/applications
### admin requires SSL
<LocationMatch "^/admin">
SSLRequireSSL
</LocationMatch>
### appadmin requires SSL
<LocationMatch "^/welcome/appadmin/.*">
SSLRequireSSL
</LocationMatch>
### serve static files directly
<LocationMatch "^/welcome/static/.*">
Order Allow,Deny
Allow from all
</LocationMatch>
### proxy all the other requests
<Location "/welcome">
Order deny,allow
Allow from all
ProxyPass http://localhost:8000/welcome
ProxyPassReverse http://localhost:8000/
</Location>
LogFormat "%h %l %u %t "%r" %>s %b" common
CustomLog /var/log/apache2/access.log common
</VirtualHost>
<VirtualHost *:443>
SSLEngine On
SSLCertificateFile /etc/apache2/ssl/server.crt
SSLCertificateKeyFile /etc/apache2/ssl/server.key
<Location "/">
Order deny,allow
Allow from all
ProxyPass http://localhost:8000/
ProxyPassReverse http://localhost:8000/
</Location>
LogFormat "%h %l %u %t "%r" %>s %b" common
CustomLog /var/log/apache2/access.log common
</VirtualHost>
The administrative interface must be disabled when web2py runs on a shared host with mod_proxy, or it will be exposed to other users.
Start as Linux daemon
Unless you are using mod_wsgi, you should setup the web2py server so that it can be started/stopped/restarted as any other Linux daemon, and so it can start automatically at the computer boot stage.
The process to set this up is specific to various Linux/Unix distributions.
In the web2py folder, there are two scripts which can be used for this purpose:
scripts/web2py.ubuntu.sh
scripts/web2py.fedora.sh
On Ubuntu, or other Debian-based Linux distribution, edit “web2py.ubuntu.sh” and replace the “/usr/lib/web2py” path with the path of your web2py installation, then type the following shell commands to move the file into the proper folder, register it as a startup service, and start it:
sudo cp scripts/web2py.ubuntu.sh /etc/init.d/web2py
sudo update-rc.d web2py defaults
sudo /etc/init.d/web2py start
On Fedora, or any other distributions based on Fedora, edit “web2py.fedora.sh” and replace the “/usr/lib/web2py” path with the path of your web2py installation, then type the following shell commands to move the file into the proper folder, register it as a startup service and start it:
sudo cp scripts/web2py.fedora.sh /etc/rc.d/init.d/web2pyd
sudo chkconfig --add web2pyd
sudo service web2py start
Nginx
Nginx is a free, open-source web server that has rapidly been gaining popularity for its amazing performance.
Unlike traditional servers, Nginx does not use threads. Instead it uses an ansynchronous/event-driven architecture to handle concurrency. This architecture results in a small and predictable memory usage, even under heavy load.
Nginx is more than an HTTP server and reverse proxy, it is also an IMAP/POP3 proxy server.
Nginx is easy to configure and its configuration files and simpler and more compact than the corresponding Apache ones.
Nginx does not support WSGI but provides native support for the uWSGI [uwsgi] protocol.
On Ubuntu you can install Nginx with:
apt-get -y install nginx-full
Then you will need to create a configuration file such as the following:
# file /etc/nginx/sites-available/web2py
server {
listen 80;
server_name $hostname;
#to enable correct use of response.static_version
#location ~* /(\w+)/static(?:/_[\d]+.[\d]+.[\d]+)?/(.*)$ {
# alias /home/www-data/web2py/applications/$1/static/$2;
# expires max;
#}
location ~* /(\w+)/static/ {
root /home/www-data/web2py/applications/;
#remove next comment on production
#expires max;
}
location / {
#uwsgi_pass 127.0.0.1:9001;
uwsgi_pass unix:///tmp/web2py.socket;
include uwsgi_params;
uwsgi_param UWSGI_SCHEME $scheme;
uwsgi_param SERVER_SOFTWARE nginx/$nginx_version;
}
}
server {
listen 443 default_server ssl;
server_name $hostname;
ssl_certificate /etc/nginx/ssl/web2py.crt;
ssl_certificate_key /etc/nginx/ssl/web2py.key;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_ciphers ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA;
ssl_protocols SSLv3 TLSv1;
keepalive_timeout 70;
location / {
#uwsgi_pass 127.0.0.1:9001;
uwsgi_pass unix:///tmp/web2py.socket;
include uwsgi_params;
uwsgi_param UWSGI_SCHEME $scheme;
uwsgi_param SERVER_SOFTWARE nginx/$nginx_version;
}
}
You will need to symlink the file and remove the default
ln -s /etc/nginx/sites-available/web2py /etc/nginx/sites-enabled/web2py
rm /etc/nginx/sites-enabled/default
You may also need to create the ssl folder for certificates and put certificates in there:
mkdir /etc/nginx/ssl
cp web2py.key /etc/nginx/ssl
cp web2py.crt /etc/nginx/ssl
You then need to install and setup uWSGI
sudo mkdir /etc/uwsgi
sudo mkdir /var/log/uwsgi
And create a configuration file “/etc/uwsgi/web2py.xml”:
<uwsgi>
<socket>/tmp/web2py.socket</socket>
<pythonpath>/home/www-data/web2py/</pythonpath>
<mount>/=wsgihandler:application</mount>
<master/>
<processes>4</processes>
<harakiri>60</harakiri>
<reload-mercy>8</reload-mercy>
<cpu-affinity>1</cpu-affinity>
<stats>/tmp/stats.socket</stats>
<max-requests>2000</max-requests>
<limit-as>512</limit-as>
<reload-on-as>256</reload-on-as>
<reload-on-rss>192</reload-on-rss>
<uid>www-data</uid>
<gid>www-data</gid>
<no-orphans/>
</uwsgi>
This file assumes web2py is installed under “/home/www-data/web2py”, as in the Apache case.
You also need to edit a second configuration file “/etc/init/uwsgi-emperor.conf”:
# Emperor uWSGI script
description "uWSGI Emperor"
start on runlevel [2345]
stop on runlevel [06]
respawn
exec uwsgi --master --die-on-term --emperor /etc/uwsgi --logto /var/log/uwsgi/uwsgi.log
Finally restart everything:
start uwsgi-emperor
/etc/init.d/nginx restart
You can reload uwsgi with
restart uwsgi-emperor
You can stop it with
stop uwsgi-emperor
You can reload web2py only (without restarting uwsgi) with
touch /etc/uwsgi/web2py.xml
All these steps are performed automatically by the provided scripts:
scripts/setup-web2py-nginx-uwsgi-on-centos.sh
scripts/setup-web2py-nginx-uwsgi-ubuntu.sh
Lighttpd
You can install Lighttpd on a Ubuntu or other Debian-based Linux distribution with the following shell command:
apt-get -y install lighttpd
Once installed, edit /etc/rc.local
and create a fcgi web2py background process
cd /var/www/web2py && sudo -u www-data nohup python fcgihandler.py &
Then, you need to edit the Lighttpd configuration file
/etc/lighttpd/lighttpd.conf
so that it can find the socket created by the above process. In the config file, write something like:
server.modules = (
"mod_access",
"mod_alias",
"mod_compress",
"mod_rewrite",
"mod_fastcgi",
"mod_redirect",
"mod_accesslog",
"mod_status",
)
server.port = 80
server.bind = "0.0.0.0"
server.event-handler = "freebsd-kqueue"
server.error-handler-404 = "/test.fcgi"
server.document-root = "/home/www-data/web2py/"
server.errorlog = "/tmp/error.log"
fastcgi.server = (
"/handler_web2py.fcgi" => (
"handler_web2py" => ( #name for logs
"check-local" => "disable",
"socket" => "/tmp/fcgi.sock"
)
),
)
$HTTP["host"] = "(^|.)example.com$" {
server.document-root="/var/www/web2py"
url.rewrite-once = (
"^(/.+?/static/.+)$" => "/applications$1",
"(^|/.*)$" => "/handler_web2py.fcgi$1",
)
}
Now check for syntax errors:
lighttpd -t -f /etc/lighttpd/lighttpd.conf
and (re)start the web server with:
/etc/init.d/lighttpd restart
Notice that FastCGI binds the web2py server to a Unix socket, not to an IP socket:
/tmp/fcgi.sock
This is where Lighttpd forwards the HTTP requests to and receives responses from. Unix sockets are lighter than Internet sockets, and this is one of the reasons Lighttpd+FastCGI+web2py is fast. As in the case of Apache, it is possible to setup Lighttpd to deal with static files directly, and to force some applications over HTTPS. Refer to the Lighttpd documentation for details.
Examples in this section were taken from John Heenan’s post in web2pyslices.
The administrative interface must be disabled when web2py runs on a shared host with FastCGI, or it will be exposed to the other users.
Shared hosting with mod_python
There are times, specifically on shared hosts, when one does not have the permission to configure the Apache config files directly. At the time of writing most of these hosts still run mod_python even if it is not maintained any more in favor of mod_wsgi.
You can still run web2py. Here we show an example of how to set it up.
Place contents of web2py into the “htdocs” folder.
In the web2py folder, create a file “web2py_modpython.py” file with the following contents:
from mod_python import apache
import modpythonhandler
def handler(req):
req.subprocess_env['PATH_INFO'] = req.subprocess_env['SCRIPT_URL']
return modpythonhandler.handler(req)
Create/update the file “.htaccess” with the following contents:
SetHandler python-program
PythonHandler web2py_modpython
#PythonDebug On
This example was provided by Niktar.
Cherokee with FastCGI
Cherokee is a very fast web server and, like web2py, it provides an AJAX-enabled web-based interface for its configuration. Its web interface is written in Python. In addition, there is no restart required for most of the changes.
Here are the steps required to setup web2py with Cherokee:
Download Cherokee[cherokee]
Untar, build, and install:
tar -xzf cherokee-0.9.4.tar.gz
cd cherokee-0.9.4
./configure --enable-fcgi && make
make install
Start web2py normally at least once to make sure it creates the “applications” folder.
Write a shell script named “startweb2py.sh” with the following code:
#!/bin/bash
cd /var/web2py
python /var/web2py/fcgihandler.py &
and give the script execute privileges and run it. This will start web2py under FastCGI handler.
Start Cherokee and cherokee-admin:
sudo nohup cherokee &
sudo nohup cherokee-admin &
By default, cherokee-admin only listens at local interface on port 9090. This is not a problem if you have full, physical access on that machine. If this is not the case, you can force it to bind to an IP address and port by using the following options:
-b, --bind[=IP]
-p, --port=NUM
or do an SSH port-forward (more secure, recommended):
ssh -L 9090:localhost:9090 remotehost
Open “http://localhost:9090“ in your browser. If everything is ok, you will get cherokee-admin.
In cherokee-admin web interface, click “info sources”. Choose “Local Interpreter”. Write in the following code, then click “Add New”.
Nick: web2py
Connection: /tmp/fcgi.sock
Interpreter: /var/web2py/startweb2py.sh
Finally, perform the following remaining steps:
- Click “Virtual Servers”, then click “Default”.
- Click “Behavior”, then, under that, click “default”.
- Choose “FastCGI” instead of “List and Send” from the list box.
- At the bottom, select “web2py” as “Application Server”
- Put a check in all the checkboxes (you can leave Allow-x-sendfile). If there is a warning displayed, disable and enable one of the checkboxes. (It will automatically re-submit the application server parameter. Sometimes it doesn’t, which is a bug).
- Point your browser to “http://yoursite“, and “Welcome to web2py” will appear.
Postgresql
PostgreSQL is a free and open source database which is used in demanding production environments, for example, to store the .org domain name database, and has been proven to scale well into hundreds of terabytes of data. It has very fast and solid transaction support, and provides an auto-vacuum feature that frees the administrator from most database maintenance tasks.
On an Ubuntu or other Debian-based Linux distribution, it is easy to install PostgreSQL and its Python API with:
sudo apt-get -y install postgresql
sudo apt-get -y install python-psycopg2
It is wise to run the web server(s) and the database server on different machines. In this case, the machines running the web servers should be connected with a secure internal (physical) network, or should establish SSL tunnels to securely connect with the database server.
Edit the PostgreSQL configuration file
sudo nano /etc/postgresql/9.1/main/postgresql.conf
and make sure it contains these two lines
...
listen_addresses = 'localhost'
...
track_counts = on
...
autovacuum = on # Enable autovacuum subprocess? 'on'
...
Edit the PostgreSQL client authentication file
sudo nano /etc/postgresql/9.1/main/pg_hba.conf
and change the method of those lines to trust
...
# "local" is for Unix domain socket connections only
local all all trust
# IPv4 local connections:
host all all 127.0.0.1/32 trust
# IPv6 local connections:
host all all ::1/128 trust
...
Start the database server with:
sudo /etc/init.d/postgresql restart
When restarting the PostgreSQL server, it should notify which port it is running on. Unless you have multiple database servers, it should be 5432.
The PostgreSQL logs are in:
/var/log/postgresql/
Once the database server is up and running, create a user and a database so that web2py applications can use it:
sudo -u postgres createuser -PE -s myuser
postgresql> createdb -O myuser -E UTF8 mydb
postgresql> echo 'The following databases have been created:'
postgresql> psql -l
postgresql> psql mydb
The first of the commands will grant superuser-access to the new user, called myuser
. It will prompt you for a password.
Any web2py application can connect to this database with the command:
db = DAL("postgres://myuser:mypassword@localhost:5432/mydb")
where mypassword
is the password you entered when prompted, and 5432 is the port where the database server is running.
Normally you use one database for each application, and multiple instances of the same application connect to the same database. It is also possible for different applications to share the same database.
For database backup details, read the PostgreSQL documentation; specifically the commands pg_dump
and pg_restore
.
Start the scheduler as a Linux service (upstart)
To install the scheduler as a permanent daemon on Linux (w/ Upstart), put the following into /etc/init/web2py-scheduler.conf, assuming your web2py instance is installed in
description "web2py task scheduler"
start on (local-filesystems and net-device-up IFACE=eth0)
stop on shutdown
respawn limit 8 60 # Give up if restart occurs 8 times in 60 seconds.
exec sudo -u <user> python /home/<user>/web2py/web2py.py -K <myapp>
respawn
You can then start/stop/restart/check status of the daemon with:
sudo start web2py-scheduler
sudo stop web2py-scheduler
sudo restart web2py-scheduler
sudo status web2py-scheduler
Initial Queuing of a Repeating Task
Task definition is done in a model file. But the initial queuing of a repeating task is most easily done from a non-exposed controller function. By doing this in a controller rather than in a model file, you remove unnecessary database accesses that would occur on every request to your website.
[The function could also be in a module or a private file, but in the controller, the web2py API and environment is readily accessible.]
A non-exposed function is any controller function that has an argument, so writing something like the following in a controller (e.g. default.py) gives you
def reinit_sched(protect=None):
# put any preparatory code here
#
# schedule 2 tasks:
sched.queue_task(foo)
sched.queue_task(bar)
#
# put any afters code here
db.commit()
and you can then easily call it with web2py.py -M -S appname/default/reinit_sched
(a similar function can be used to stop a repeating task, perhaps for maintenance reasons)
Populating a Database on Deployment
Your application may have a need for a pre-populated database table. A simple example might be a table of color names, or the names of the months (perhaps in a special format not used in Python datetime routines). More complicated examples might include an initial inventory of parts, or the initial pages of a wiki.
The simple examples might be done via db.mycolors.insert()
; the more complex examples might use a CSV file to fill in the values. As in the task queuing section above, this should be done using non-exposed controller functions. Table definition for a database is done in model files, but model files are read on every request, so one-time actions should not be in the model files where they would lower the responsiveness of your site.
[The function could also be in a module or a private file, but in the controller, the web2py API and environment is readily accessible.]
Again, a non-exposed function is any controller function that has an argument, so writing something like the following in a controller (e.g. default.py) gives you
def populate_colors(protected=None)
collist = ["lime", "#00FF00", "olive", "#808000",
"fuchsia", "#FF00FF", "maroon", "#800000"]:
for i in range(0, len(collist), 2):
k, v = collist[i:i+2]
db.mycolors.insert(name=k, code=v)
db.commit()
you can then easily call it with web2py.py -M -S appname/default/populate_colors
For the complex example using a CSV file, your function might look like:
def populate_colors(exposed=False):
db.mycolors.import_from_csv_file(
open(os.path.join(request.folder,
os.path.join('private', db_colors.csv')
),
'r')
)
db.commit()
and this would be called with web2py.py -M -S appname/default/populate_colors
See also Chapter 14, Populating database with dummy