I try to make the Pyramid Single File Tasks Tutorial runs under mod_wsgi, and figure that two changes are needed to make it runs both standalone (http://localhost:6543) and under mod_wsgi (http://localhost/task).
I would like to share these two changes:
[tasks.py]
FROM:
if __name__ == '__main__':
# configuration settings
settings = {}
settings['reload_all'] = True
settings['debug_all'] = True
settings['mako.directories'] = os.path.join(here, 'templates')
settings['db'] = os.path.join(here, 'tasks.db')
# session factory
session_factory = UnencryptedCookieSessionFactoryConfig('itsaseekreet')
# configuration setup
config = Configurator(settings=settings, session_factory=session_factory)
# routes setup
config.add_route('list', '/')
config.add_route('new', '/new')
config.add_route('close', '/close/{id}')
# static view setup
config.add_static_view('static', os.path.join(here, 'static'))
# scan for @view_config and @subscriber decorators
config.scan()
# serve app
app = config.make_wsgi_app()
server = make_server('0.0.0.0', 8080, app)
server.serve_forever()
TO:
def get_app():
# configuration settings
settings = {}
settings['reload_all'] = True
settings['debug_all'] = True
settings['mako.directories'] = os.path.join(here, 'templates')
settings['db'] = os.path.join(here, 'tasks.db')
# session factory
session_factory = UnencryptedCookieSessionFactoryConfig('itsaseekreet')
# configuration setup
config = Configurator(settings=settings, session_factory=session_factory)
# routes setup
config.add_route('list', '/')
config.add_route('new', '/new')
config.add_route('close', '/close/{id}')
# static view setup
config.add_static_view('static', os.path.join(here, 'static'))
# scan for @view_config and @subscriber decorators
config.scan()
# serve app
app = config.make_wsgi_app()
return app
application = get_app()
if __name__ == '__main__':
server = make_server('0.0.0.0', 8080, application)
server.serve_forever()
[templates/layout.mako]
FROM:
<link rel="shortcut icon" href="/static/favicon.ico">
<link rel="stylesheet" href="/static/style.css">
TO:
<link rel="shortcut icon" href="${request.application_url}/static/favicon.ico">
<link rel="stylesheet" href="${request.application_url}/static/style.css">
I am using Debian 6, and the following is the relevant section in /etc/apache2/mods-enabled/wsgi.conf, where task.wsgi is a symbolic link to task.py in the same directory.
WSGIApplicationGroup %{GLOBAL}
WSGIPassAuthorization On
WSGIDaemonProcess pyramid user=david group=david threads=4 \
python-path=/home/david/tasks/env/lib/python2.6/site-packages
WSGIScriptAlias /task /home/david/tasks/env/task/task.wsgi
<Directory /home/david/tasks/env>
WSGIProcessGroup pyramid
Order allow,deny
Allow from all
</Directory>
[end]
Showing posts with label mod_wsgi. Show all posts
Showing posts with label mod_wsgi. Show all posts
2013-05-14
Set up Django 1.5.1 in DreamHost VPS
This post is about setting up Django 1.5.1 in a virtualenv in DreamHost VPS with Apache2 and mod_wsgi 3.4, and is mostly an update to the following post about three years ago:
1. Sign up a VPS account with DreamHost.
2. Create a regular user [user] in the VPS. The Django project will run under this account.
http://www.wombatnation.com/2010/06/django-on-dreamhost-ps/comment-page-1
Software Versions:
Apache 2.2.22
Django 1.5.1
mod_wsgi 3.4
PIP 1.3.1
Python 2.6.6
VirtualEnv 1.9.1
2. Create a regular user [user] in the VPS. The Django project will run under this account.
3. Create an admin user [admin] in the VPS to manage the web server. This admin account has sudo privileges.
4. Install Python PIP (1.3.1)
[admin]$ sudo easy_install pip
PIP is installed at /usr/local/bin/pip.
5. Upgrade VirtualEnv (from 1.4.9 to 1.9.1)
[admin]$ sudo pip install --upgrade virtualenv
6. Create a virtualenv and install Django (1.5.1) in it
[user]$ mkdir ~/django
[user]$ virtualenv ~/django/env
[user]$ source ~/django/env/bin/activate
[env]$ pip install django
7. Create a Django project (demo)
[env]$ cd ~/django
[env]$ django-admin.py startproject demo
8. Verify Django project is working
[env]$ cd ~/django/demo
[env]$ python manage.py runserver 0.0.0.0:8000
Visit http://your.domain.com:8000 to verify Django project is up and running.
9. Install mod_wsgi 3.4
[admin]$ mkdir ~/src
[admin]$ cd ~/src
[admin]$ wget http://modwsgi.google.com/files/mod_wsgi-3.4.tar.gz
[admin]$ tar xzvf mod_wsgi-3.4.tar.gz
[admin]$ cd mod_wsgi-3.4
[admin]$ ./configure --with-apxs=/usr/local/dh/apache2/template/sbin/apxs --with-python=/usr/bin/python
[admin]$ make
[admin]$ sudo make install
mod_wsgi is installed at /usr/local/dh/apach2/template/lib/modules/mod_wsi.so
10. Edit httpd.conf
[admin]$ sudo vim /usr/local/dh/apache2/apache2-psNNNNNN/etc/httpd.conf
psNNNNNN is your VPS id.
add the following line in the LoadModule section:
LoadModule wsgi_module /dh/apache2/template/lib/modules/mod_wsgi.so
add the following line outside of VirtualHost directive:
WSGIPythonPath /home/user/django/env/lib/python2.6/site-packages
add following line inside the VirtualHost directive:
WSGIScriptAlias /demo /home/user/django/demo/demo/wsgi.py
11. Restart Apache
[admin]$ sudo /etc/init.d/httpd2 restart apache2-psNNNNNN
12. Edit wsgi.py
[env]$ vim ~/django/demo/demo/wsgi.py
add next two lines at the top of the file:
import sys
sys.path.insert(0, '/home/user/django/demo')
13. Create a Django app (demoapp) and update urls.py
[env]$ cd ~/django/demo
[env]$ python manage.py startapp demoapp
[env]$ vim ~/django/demo/demoapp/views.py
Make it look like:
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello world!")
[env]$ vim ~/django/demo/demo/urls.py
Add a url pattern:
url(r'^$', 'demoapp.views.index')
14. Verify
Visit http://your.domain.com/demo, will see "Hello World!" in browser.
-End-
2013-04-10
Password protect a PDF
The othe day, I wrote a CherryPy application that add a password to the PDF, and run it behind Apache2 with the mod_wsgi module. The actual adding of password is done by pdftk console tool.
The entire CherryPy application is in one file main.py as below.
The index() method presents the UI to the web browser, asking the user to select the PDF and enter a password.
The upload() method shells out to the console and calls pdftk to add the password, and then returns the password-protected file back to the browser, letting the user to save the PDF to local storage (e.g. the user's hard disk).
The last part of the file deals with hooking it up with Apache2/mod_wsgi. If main.py is run from the command line, then the CherryPy built-in HTTP server will start, otherwise, it assumes it is run behind Apache2 and a WSGI application is created.
# main.py
# requires cherrypy
# requires pdftk (command line tool)
# dkf 130401 creation
import os
import tempfile
import cherrypy
class PdfPass(object):
def index(self):
return """
<html><body>
<h2>Add password to PDF</h2>
<form action="upload" method="post" enctype="multipart/form-data">
<table>
<tr>
<td>Select PDF:</td>
<td><input type="file" name="pdf" size="60"/></td>
</tr>
<tr>
<td>Password:</td>
<td><input type="password" name="pass1" value="" size="20" maxlength="40"/></td>
</tr>
<tr>
<td>Password again:</td>
<td><input type="password" name="pass2" value="" size="20" maxlength="40"/></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="Add password"/></td>
</tr>
</table>
</form>
</body></html>
"""
index.exposed = True
def upload(self, pdf, pass1, pass2):
if not pass1:
return "Password cannot be emply!<br/>Please go back and correct."
if pass1 != pass2:
return "Passwords do not match!<br/>Please go back and correct."
# read in the user uploaded pdf
temp1 = tempfile.mktemp()
with open(temp1, "wb") as f:
f.write(pdf.file.read())
f.close()
# call pdftk to add password to pdf
temp2 = tempfile.mktemp()
os.system('pdftk %s output %s user_pw %s' % (temp1, temp2, pass1))
with open(temp2, "rb") as f:
data = f.read()
f.close()
# clean up temp files
os.remove(temp1)
os.remove(temp2)
# deliver the password protected pdf to the user
cherrypy.response.headers['Content-Type'] = "application/pdf"
cherrypy.response.headers['Content-Disposition'] = 'attachment, filename="%s"' % pdf.filename
return data
upload.exposed = True
if __name__ == '__main__':
cherrypy.quickstart(PdfPass())
else:
# cherrypy.config.update({'environment': 'embedded'})
application = cherrypy.Application(PdfPass(), script_name=None, config=None)
On the Apache side (Apache2 in Debian6), need to modify the /etc/apache2/sites-available/default, adding the following lines inside the <VirtualHost *.80> block. Then the CherryPy application will be available at http://localhost/<url>.
# must run wsgi in daemon mode otherwise content-disposition may not work
WSGIDaemonProcess cherrypy processes=2 threads=15 display-name=%{GROUP}
WSGIProcessGroup cherrypy
WSGIScriptAlias /<url> /full/path/to/main.py
<Directory /full/path/to>
Order allow,deny
allow from all
</Directory>
-End-
The entire CherryPy application is in one file main.py as below.
The index() method presents the UI to the web browser, asking the user to select the PDF and enter a password.
The upload() method shells out to the console and calls pdftk to add the password, and then returns the password-protected file back to the browser, letting the user to save the PDF to local storage (e.g. the user's hard disk).
The last part of the file deals with hooking it up with Apache2/mod_wsgi. If main.py is run from the command line, then the CherryPy built-in HTTP server will start, otherwise, it assumes it is run behind Apache2 and a WSGI application is created.
# main.py
# requires cherrypy
# requires pdftk (command line tool)
# dkf 130401 creation
import os
import tempfile
import cherrypy
class PdfPass(object):
def index(self):
return """
<html><body>
<h2>Add password to PDF</h2>
<form action="upload" method="post" enctype="multipart/form-data">
<table>
<tr>
<td>Select PDF:</td>
<td><input type="file" name="pdf" size="60"/></td>
</tr>
<tr>
<td>Password:</td>
<td><input type="password" name="pass1" value="" size="20" maxlength="40"/></td>
</tr>
<tr>
<td>Password again:</td>
<td><input type="password" name="pass2" value="" size="20" maxlength="40"/></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="Add password"/></td>
</tr>
</table>
</form>
</body></html>
"""
index.exposed = True
def upload(self, pdf, pass1, pass2):
if not pass1:
return "Password cannot be emply!<br/>Please go back and correct."
if pass1 != pass2:
return "Passwords do not match!<br/>Please go back and correct."
# read in the user uploaded pdf
temp1 = tempfile.mktemp()
with open(temp1, "wb") as f:
f.write(pdf.file.read())
f.close()
# call pdftk to add password to pdf
temp2 = tempfile.mktemp()
os.system('pdftk %s output %s user_pw %s' % (temp1, temp2, pass1))
with open(temp2, "rb") as f:
data = f.read()
f.close()
# clean up temp files
os.remove(temp1)
os.remove(temp2)
# deliver the password protected pdf to the user
cherrypy.response.headers['Content-Type'] = "application/pdf"
cherrypy.response.headers['Content-Disposition'] = 'attachment, filename="%s"' % pdf.filename
return data
upload.exposed = True
if __name__ == '__main__':
cherrypy.quickstart(PdfPass())
else:
# cherrypy.config.update({'environment': 'embedded'})
application = cherrypy.Application(PdfPass(), script_name=None, config=None)
On the Apache side (Apache2 in Debian6), need to modify the /etc/apache2/sites-available/default, adding the following lines inside the <VirtualHost *.80> block. Then the CherryPy application will be available at http://localhost/<url>.
# must run wsgi in daemon mode otherwise content-disposition may not work
WSGIDaemonProcess cherrypy processes=2 threads=15 display-name=%{GROUP}
WSGIProcessGroup cherrypy
WSGIScriptAlias /<url> /full/path/to/main.py
<Directory /full/path/to>
Order allow,deny
allow from all
</Directory>
-End-
Subscribe to:
Posts (Atom)