mvc.py provides mvc support to the existing web.py python framework.
- Python 2.6+
- web.py 0.36+
Install web.py using pip:
$ pip install web.pyDownload mvc.py:
$ wget --no-check-certificate https://github.com/fedecarg/webpy-mvc/archive/master.tar.gz $ tar xzvf master.tar.gzStart up the web server:
$ cd webpy-mvc-master/src $ python app.pyHave a cup of tea (optional)
The configuration file config/application.py and environment-specific configuration files allow you to specify the various settings that you want to pass down to the mvc.py module.
For example, the default config/application.py file includes this setting:
# debug error messagesweb.config.debug=Trueweb.py works with many database systems, including MySQL, PostgreSQL and SQLite.
SQLite
web.config.database=web.database(dbn='sqlite', db='db/example.sqlite')MySQL and Postgres
If you choose to use MySQL or Postgres instead of the shipped SQLite database, your config/application.py will look something like this:
web.config.database=web.database(dbn='mysql', user='username', pw='password', db='example')web.py's URL handling scheme is simple yet powerful and flexible. at the top of each application, you usually see the full URL dispatching scheme defined as a tuple:
urlpatterns= (
'/books/new', {'controller':'books', 'action':'new'},
'/books/create', {'controller':'books', 'action':'create'},
'/books', {'controller':'books', 'action':'index'},
'/', {'controller':'index', 'action':'index'}
)Routes have priority defined by the order of appearance of the routes. The priority goes from top to bottom. The last route in that file is at the lowest priority will be applied last. If no route matches, 404 is returned.
You can utilize the power of regular expressions to design more flexible url patterns. For example, /books/(new|create) will catch either new or create. The key point to understand is that this matching happens on the path of your URL. For example:
urlpatterns= (
'/books/(new|create)', {'controller':'books', 'action':'{0}'},
'/books', {'controller':'books', 'action':'index'},
'/', {'controller':'index', 'action':'index'}
)In the url pattern you can catch parameters which can be used in your handler class:
urlpatterns= (
'/books/(new|create)', {'controller':'books', 'action':'{0}'},
'/books/(\d+)/(edit|delete)', {'controller':'books', 'action':'{1}', 'id':'{0}'},
'/books/(\d+)', {'controller':'books', 'action':'show', 'id':'{0}'},
'/books', {'controller':'books', 'action':'index'},
'/', {'controller':'index', 'action':'index'}
)Controller classes inherit from ApplicationController, a base class that contains code that can be run in all your controllers. Controllers are made up of one or more actions that are executed on request and then either render a template or redirect to another action. It's up to you what name you want to give to these methods. Everything is done very much “the rails way”. Here is a sample rails controller and its equivalent in mvc.py:
classBooksController < ApplicationControllerdefindex@books=Book.find(:all)enddefshow@book=Book.find(params[:id])enddefnew@book=Book.new@subjects=Subject.find(:all)enddefcreate@book=Book.new(params[:book])if@book.saveredirect_to:action=>'index'else@subjects=Subject.find(:all)render:action=>'new'endenddefdeleteBook.find(params[:id]).destroyredirect_to:action=>'index'endendclassBooksController(ApplicationController)
defindex(self):
self.books=Book.find("all")
defshow(self, id):
self.book=Book.find(id)
defnew(self):
self.book=Book()
self.subjects=Subject.find("all")
defcreate(self):
self.book=Book(self.input('book'))
ifself.book.save():
self.redirect_to(action="index")
else:
self.subjects=Subject.find("all")
self.render("new") defdelete(self, id):
Book.find(id).delete()
self.redirect_to(action='index')If you look in the app/views directory, you will see one subdirectory for each of the controllers we have in app/controllers. Application Controller sends content to the user by using the render method, which enables rendering of HTML templates:
classBooksController(ApplicationController)
defindex(self):
returnself.render(title='home')Accessing URL parameters in your controller action:
classBooksController(ApplicationController)
defedit(self, id):
returnself.render(id=id)Rendering a view that corresponds to a different action within the same controller:
classBooksController(ApplicationController)
defindex(self):
returnself.render('foo')Rendering an action's template from another controller:
classBooksController(ApplicationController)
defindex(self):
returnself.render('books/index')Specifying a layout for a current controller:
classBooksController(ApplicationController)
layout='mobile'defindex(self):
returnself.render()Specifying a layout for a current action:
classBooksController(ApplicationController)
defindex(self):
returnself.render(layout='mobile')Using the initialize method to put default values into instance variables:
classBooksController(ApplicationController)
definitialize(self):
self.title='home page'defindex(self):
returnself.render(title=self.title)By default an application will render either a 404 or a 500 error message. These messages are contained in static HTML files in the app/views/errors folder, in 404.html and 500.html respectively. You can customize these files to add some extra information and layout.
If for whatever reason you spot something to fix but cannot patch it yourself, please open an issue. Also, any kind of discussion regarding web frameworks is more than welcome @fedecarg