Most Web applications are not self-contained - instead of providing information which is written into the application code itself, they may often access data from other places or even communicate with other systems. Since applications may be very different in the way that they access external systems or the way in which they obtain external information, WebStack does not mandate rigid mechanisms for hooking into such systems or loading such information. Instead, it is recommended that applications import packages and modules which provide the functionality necessary to carry out such integration.
Examples of packages and modules that might be used for integration purposes include the following:
In the simplest of cases, the use of external packages is as straightforward as importing a Python module (or package) and then using that module's contents. This can often be done in the resource code; for example:
import urllib
class MyResource:
def respond(self, trans):
[Examine the transaction, decide what the user wants to do.]
f = urllib.urlopen("http://www.boddie.org.uk/rss/feed.xml")
[Produce some kind of response which tells the user what happened.]
In the above example, here is what happens:
What we do | Where it happens and how often |
---|---|
Import urllib
to gain access to functionality which we can then use to access a
remote service. |
This happens once - when the above code is itself imported into Python. |
Use the urlopen
function of urllib to actually access a remote service. |
This happens in the resource code each time the resource decides to access the service. |
In this case, the functionality is relatively easy to acquire and does not require any initialisation. But what if we were connecting to a database? There might be a need to specially initialise the database module - only once, though - and then repeatedly use it. Consider this highly artificial example:
import mydb
connection = mydb.connect("me", "myPassword")
class MyResource:
def respond(self, trans):
[Examine the transaction, decide what the user wants to do.]
results = connection.query("feed", owner="boddie.org.uk")
[Produce some kind of response which tells the user what happened.]
In the above example, here is what happens:
What we do | Where it happens and how often |
---|---|
Import the mydb
module to gain access to database access functionality. |
This happens once - when the above code is itself imported into Python. |
Initialise a database
connection using the connect function from the mydb
module. |
This also happens only once - when the above code is itself imported into Python. |
Use the query
method on the connection object to access a database. |
This happens in the resource code each time the resource decides to access the database. |
The choice of initialising the connection may seem arbitrary - why
not just obtain a connection in the resource? Usually, such decisions
are made on the basis of efficiency and on constraints outside the
control of the application - some database systems limit the number of
connections, for example, and if a large number of resources suddenly
became active, some of them would fail to obtain connections if the
connection initialisation code were in the respond
method of the resource.
Of course, the above resource might not be the only resource to use database connections. It might then be tempting to initialise a connection for each module whose resource needs (or, since as normal Python classes we can put many resources in a single module, whose resources need) to access a database. But it would surely be more convenient to define a single, central place to hold such global resources.
One approach is to define a module which can be accessed by all
modules, and thus by all resources. Let us create such a module in the
file Properties.py
which will reside alongside MyApplication.py
(or whatever the application module is called). Inside the Properties
module we can write the following code:
import mydb
connection = mydb.connect("me", "myPassword")
Now, in each module containing resources which need to access the
database, all we need to do now is to import the Properties
module and to use the connection as defined in that module:
import Properties
class MyResource:
def respond(self, trans):
[Examine the transaction, decide what the user wants to do.]
results = Properties.connection.query("feed", owner="boddie.org.uk")
[Produce some kind of response which tells the user what happened.]
This is a very simple approach that is technically outclassed by the mechanisms available in some frameworks. Currently, WebStack does not provide access to those more sophisticated mechanisms, however.