RapidSMS Developers Guide/Creating a RapidSMS App
App structure
editA RapidSMS App is a Django app which includes some RapidSMS-specific files and follows some conventions. A Typical app would look like this:
__init__.py app.py models.py admin.py views.py urls.py static/ templates/
A minimal app would contain:
__init__.py app.py
- app.py: SMS code
- models.py: Django models (database)
- admin.py: Django admin
- views.py: Django view (web interface)
- urls.py: Djangi URL patterns (for web interface)
- static/: folder containing static files for web interface. Accessible at http://<server>/static/<appname>/
- templates: Django templates
SMS Code
editAn App's SMS code is composed of a rapidsms.app.App class which will be instantiated and called by the router.
Skeleton of a app.py:
import rapidsms class App(rapidsms.app.App): def parse(self, message): pass def handle(self, message): pass
How it works ?
editThe router, launched by the route command, instantiates all the App's App classes. This is done in the order of the apps= string in local.ini ; then it calls the start method of each, then the configure message of each.
Once a message is received, it follows the following procedure:
- call parse method of each App, passing it the Message object.
- class handle method of each App, passing it the Message object.
Once one of the handle method return True, the message is considered handled and thus not passed to the other apps. That's why order matters.
Configuring your App
editRapidSMS offers the ability to add some configuration for your app in the local.ini file. In your local.ini, add a section for your app with key-value peers.
Example for a test app:
[test] country=ml
Adding such configuration will have the router call the configure method of the test App during startup. Make sure your app has a configure method that can answer to it :
def configure(self, country): pass
or
def configure(self, **kwargs): pass
Note that all arguments are passed as strings.
Message Object
editThe Message object is at the heart of RapidSMS. It is the one carrying the SMS from the backend, to the router, then back to the backend for delivery to the user.
Properties
edit- message.text: the actual text message. This can be a str or a unicode text. There is no size limitation.
- message.peer: sender/recipient identity. Depending on backend, this is usually a string representing the phone number or equivalent.
- message.date: a datetime object representing the reception date.
- message.status: a string representing the status of the message. Not widely used.
- message.person: a Person object which hold a reference to the connection
- message.connection: a Connection object which holds reference to both the backend and the identity.
Methods
edit- message.send(): sends the object to the appropriate backend.
- message.respond(text, status): creates a message to send back to the sender of this one. Actual sending is differed.
- message.flush_responses(): sends all responses created with .respond()
- message.forward(identity, text): creates a new message object on same backend with different identity then call respond().
Models
editMost RapidSMS Apps are used for Data Collection and rely on a Database. Because RapidSMS is built on top of Django, you are encouraged to use Django's Models for this.
Since nothing here is specific to RapidSMS, please refer to Django Documentation[1]
Example
editCreating a model
editA model resides in models.py file and should subclass django.db.models.Model:
from django.db import models class SMS(models.Model): number = models.CharField(max_length=30) text = models.TextField()
This model contains 2 properties: number and text, both are strings.
Django's Models are an ORM (Object Relational Mapping). This means that from your apps, you will instantiate those objects like live objects and django will take care of storage/retrieval to/from the database.
Important: Your model is just the representation of your data. You can consider it like the list of your tables fields. Each time you modify it, you will need to ask Django to update the actual database, which is separate.
Creating the database
editAs stated above, Django will be entirely responsible for Database access. Just make sure your local.ini is correctly configured regarding the Database then re-sync the Database.
./rapidsms syncdb
This command will create every newly added model.
Should you need to modify your model, you will have to erase and re-create the database:
./rapidsms reset <appname>
Dumping and restoring Data
editDjango includes a tool to backup and restore the content of your Database (models).
./rapidsms dumpdata <appname>
This will display a serialized version of all your models data for the app appname. You can also select one particular model.
./rapidsms dumpdata <appname>.SMS > backup.json
The previous command will save the content of the SMS model only and redirect it to a file. The default format for dumping and restoring datas in Django is JSON.
To restore a backup file, use the following
./rapidsms loaddata backup.json
Views
editIn Django-terminology, views are web pages.
Please, refer to documentation as none of the following is RapidSMS specific.
To display a web-page, the django way, you need to complete three steps:
Set the URL
editThe file urls.py keeps a record of all your app's URLs. You need each of your views (pages) to be defined in urls.py in order to access them.
Example for an app named test:
from django.conf.urls.defaults import * import test.views as views urlpatterns = patterns('', url(r'^test/?$', views.index), )
The above file will call the index view (nonexistent right now) for each HTTP request to http://<server>/test.
Create a template
editTo save the developer some time and effort with dealing with HTML, Django offers the ability to use templates. A template is an HTML file which can accept a particular syntax to display variables and other data from the view.
Create a sample RapidSMS template in the templates/ folder:
{% extends base_template %} {% block content %} <p>Hello {{ name }}!</p> {% endblock %}
This template extends the base_template one (which is RapidSMS's design) and replace the content of the block content with a paragraph. This paragraph contain a template variable which we will have replaced by some text in the view.
Create an HTTP function
editA view is just a function which return an HTTP object to be displayed on the visitor's browser.
A minimal views.py file:
from django.http import HttpResponse def index(request): return HttpResponse("hello")
With this view, displaying the corresponding web page on a browser will result in a blank page with the word hello.
Instead of writing HTML inside our view, we can call the template we just created.
On this, Django and RapidSMS differs a little. Here is the RapidSMS way:
from rapidsms.webui.utils import render_to_response def index(request): greeting = "Thomas" return render_to_response(request, 'templates/index.html', {'name': greeting})
This way, we are displaying a template and passing it a context (Hash) containing a list of our template-variables and their associated values.
Displaying it in a browser will result in a nice RapidSMS U.I with a sentence greeting Thomas.
Django Admin
editTo access the Data corresponding to your models visually, you can enable the Django admin. Django provide a web interface for administering some of its features but also the models created by developers.
It is accessible at http://<server>/admin.
Refer to Customizing Admin U.I to enable it for your App.