merged with sms app loaded

This commit is contained in:
Johnson Chetty 2012-03-07 13:37:35 +01:00
commit fad6095808
19 changed files with 635 additions and 22 deletions

View File

@ -51,7 +51,7 @@ class FareAdmin(admin.ModelAdmin):
class UniqueRouteAdmin(admin.ModelAdmin): class UniqueRouteAdmin(admin.ModelAdmin):
list_display = ("route","from_stop", "to_stop","distance","is_full") list_display = ("route","from_stop", "to_stop","distance","is_full")
readonly_fields = ("route","from_stop", "to_stop","distance","is_full") readonly_fields = ("route","from_stop", "to_stop","distance","is_full")
search_fields = ("route", "from_stop__name", "to_stop__name") search_fields = ("route__alias", "from_stop__name", "to_stop__name")
ordering = ('route',) ordering = ('route',)
list_per_page = 50 list_per_page = 50

View File

@ -3,6 +3,7 @@ from ox.django.shortcuts import get_object_or_404_json, render_to_json_response
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
import json import json
from django.views.decorators.csrf import csrf_exempt from django.views.decorators.csrf import csrf_exempt
import re
def route(request, slug): def route(request, slug):
srid = int(request.GET.get("srid", 4326)) srid = int(request.GET.get("srid", 4326))
@ -29,28 +30,45 @@ def area(request, slug):
}) })
def routes(request): def routes(request):
q = request.GET.get("q", "")
in_regex = re.compile(r'(\d{1,3})') # used to extract the route number string out of the query string - for eg, gets "21" from "21Ltd"
match = re.findall(in_regex, q)
if match:
route_no = match[0]
else:
route_no = ''
ret = []
if route_no != '':
out_regex = re.compile(r'.*(\D|\A)%s(\D|\Z).*' % route_no) # used for, for eg. to filter out '210Ltd' when user searches for '21'. Checks for non-digit or start of string, followed by route_no, followed by non-digit or end of string
qset = Route.objects.filter(alias__icontains=route_no)
for route in qset:
if re.match(out_regex, route.alias):
ret.append(route.alias)
else:
qset = Route.objects.all() qset = Route.objects.all()
if request.GET.has_key('q'): for route in qset:
q = request.GET.get('q', '') ret.append(route.alias)
qset = qset.filter(alias__icontains=q) #FIXME: make a better Q object # routes = [route.alias for route in qset]
routes = [route.alias for route in qset] return render_to_json_response(ret)
return render_to_json_response(routes)
def areas(request): def areas(request):
q = request.GET.get("q", "")
if q != '':
qset = Area.objects.find_approximate(q, 0.33)
else:
qset = Area.objects.all() qset = Area.objects.all()
if request.GET.has_key('q'):
q = request.GET.get('q', '')
qset = qset.filter(display_name__icontains=q)
areas = [area.slug for area in qset] areas = [area.slug for area in qset]
return render_to_json_response(areas) return render_to_json_response(areas)
def stops(request): def stops(request):
q = request.GET.get("q", "")
if q != '':
qset = Stop.objects.find_approximate(q, 0.33)
else:
qset = Stop.objects.all() qset = Stop.objects.all()
srid = int(request.GET.get("srid", 4326)) srid = int(request.GET.get("srid", 4326))
if request.GET.has_key('q'):
q = request.GET.get('q', '')
qset = qset.filter(display_name__icontains=q) #FIXME: This definitely needs to be a Q object with OR lookups for area name, road name, etc.
return render_to_json_response({ return render_to_json_response({
'type': 'FeatureCollection', 'type': 'FeatureCollection',
'features': [stop.get_geojson(srid=srid) for stop in qset] 'features': [stop.get_geojson(srid=srid) for stop in qset]

View File

View File

@ -0,0 +1,20 @@
from django.core.management.base import BaseCommand, CommandError
from django.db import connection
from mumbai import models
class Command(BaseCommand):
help = "Instantiates the pg_trgm indexes"
def handle(self, *args, **options):
cursor = connection.cursor()
for name in dir(models):
model = getattr(models, name)
if not hasattr(model, "objects") or \
not isinstance(model.objects, models.TrigramSearchManager):
continue
table = model._meta.db_table
for column in model.objects.trigram_columns:
sql = """CREATE INDEX %s_%s_trgm_idx ON %s USING gin (%s gin_trgm_ops);""" % (
table, column, table, column)
cursor.execute(sql)
cursor.execute("COMMIT;")

View File

@ -3,6 +3,7 @@ from django.contrib.gis.geos import Point
from django import forms from django import forms
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic from django.contrib.contenttypes import generic
from django.db import connection
import json import json
STOP_CHOICES = ( ('U','Up'), STOP_CHOICES = ( ('U','Up'),
@ -42,7 +43,32 @@ SCHED = {
'2nd &4th':['???'] '2nd &4th':['???']
} }
class TrigramSearchManager(models.Manager):
def __init__(self, trigram_columns=[]):
super(TrigramSearchManager, self).__init__()
self.trigram_columns = trigram_columns
def set_threshold(self, threshold):
"""Set the limit for trigram similarity matching."""
cursor = connection.cursor()
cursor.execute("""SELECT set_limit(%f)""" % threshold)
def find_approximate(self, text, match=0.5):
self.set_threshold(match)
similarity_measure = "greatest(%s)" % ",".join(["similarity(%s, %%s)" % col for col in self.trigram_columns])
similarity_filter = " OR ".join(["%s %%%% %%s" % col for col in self.trigram_columns])
text_values = [text] * len(self.trigram_columns)
qset = self.get_query_set()
# use the pg_trgm index via the % operator
qset = qset.extra(select={"similarity":similarity_measure},
select_params=text_values,
where=[similarity_filter],
params=text_values,
order_by=["-similarity"])
return qset
class Area(models.Model): class Area(models.Model):
objects = TrigramSearchManager(("name", "name_mr", "display_name"))
code = models.IntegerField() #primary_key=True) code = models.IntegerField() #primary_key=True)
slug = models.SlugField(null=True) slug = models.SlugField(null=True)
name = models.TextField(blank=True, max_length=255) name = models.TextField(blank=True, max_length=255)
@ -91,8 +117,8 @@ class Fare(models.Model):
def __unicode__(self): def __unicode__(self):
return str(self.slab) return str(self.slab)
class Stop(models.Model): class Stop(models.Model):
objects = TrigramSearchManager(("name", "name_mr", "display_name"))
code = models.IntegerField() code = models.IntegerField()
slug = models.SlugField(null=True) slug = models.SlugField(null=True)
name = models.TextField(blank=True, max_length=255) name = models.TextField(blank=True, max_length=255)
@ -123,7 +149,7 @@ class Stop(models.Model):
} }
def get_geojson(self, srid=4326): def get_geojson(self, srid=4326):
print srid # print srid
if self.point is not None: if self.point is not None:
geom = json.loads(self.point.transform(srid, True).geojson) geom = json.loads(self.point.transform(srid, True).geojson)
else: else:
@ -178,7 +204,7 @@ class Stop(models.Model):
class Route(models.Model): class Route(models.Model):
code = models.TextField(max_length=255, unique=True) code = models.TextField(max_length=255, unique=True) #FIXME: Why is this a TextField??
slug = models.SlugField(null=True) slug = models.SlugField(null=True)
alias = models.TextField(max_length=255) alias = models.TextField(max_length=255)
from_stop_txt = models.TextField(max_length=500) from_stop_txt = models.TextField(max_length=500)
@ -188,6 +214,9 @@ class Route(models.Model):
distance = models.DecimalField(max_digits=3, decimal_places=1) distance = models.DecimalField(max_digits=3, decimal_places=1)
stages = models.IntegerField() stages = models.IntegerField()
class Meta:
ordering = ['code']
def get_absolute_url(self): def get_absolute_url(self):
return "/route/%s/" % self.alias return "/route/%s/" % self.alias

View File

@ -23,7 +23,7 @@ var API_BASE = "/1.0/",
var $li = $('<div />') var $li = $('<div />')
.addClass("listItem") .addClass("listItem")
.appendTo($list); .appendTo($list);
var $txt = $('<span >').addClass("listItemText").text(v).appendTo($li); var $txt = $('<span />').addClass("listItemText").text(v).appendTo($li);
}); });
}); });
} }
@ -51,6 +51,7 @@ var API_BASE = "/1.0/",
$('.selectedListItem').find(".stopsList").hide().remove(); $('.selectedListItem').find(".stopsList").hide().remove();
$('.selectedListItem').removeClass("selectedListItem"); $('.selectedListItem').removeClass("selectedListItem");
$target.addClass("selectedListItem"); $target.addClass("selectedListItem");
if ($target.data("hasList")) { if ($target.data("hasList")) {
var $stopsList = $target.find(".stopsList"); var $stopsList = $target.find(".stopsList");
$stopsList.slideDown(); $stopsList.slideDown();
@ -223,12 +224,15 @@ var API_BASE = "/1.0/",
var geojsonString = JSON.stringify(geojson); var geojsonString = JSON.stringify(geojson);
//console.log(geojsonString); //console.log(geojsonString);
var url = API_BASE + "stop/" + stop.slug + "?srid=3857"; var url = API_BASE + "stop/" + stop.slug + "?srid=3857";
$.post(url, {'geojson': geojsonString}, function(response) { var $postXHR = $.post(url, {'geojson': geojsonString}, function(response) {
if (response.errors) { if (response.errors) {
alert("error saving"); alert("error saving");
} }
//console.log(response); //console.log(response);
}, "json"); }, "json");
$postXHR.fail(function(e) {
alert('failed ' + JSON.stringify(e));
});
}); });
return $div; return $div;
} }
@ -318,6 +322,7 @@ var API_BASE = "/1.0/",
// console.log(e.feature); // console.log(e.feature);
var slug = e.feature.attributes.slug; var slug = e.feature.attributes.slug;
//alert("selected " + slug); //alert("selected " + slug);
$('.selectedStop').removeClass("selectedStop");
highlightStop(slug); highlightStop(slug);
var stop = e.feature.attributes; var stop = e.feature.attributes;
var geom = { var geom = {

11
gateway/README Normal file
View File

@ -0,0 +1,11 @@
These files make the SMS gateway on atlas go.
* apt-get install supervisor
* Create a virtualenv in /srv/smsBEST
* Install RapidSMS to the virtualenv:
http://github.com/schuyler/rapidsms
* rapidsms-admin.py startproject gateway
* Put settings.py in /srv/smsBEST/gateway
* Run manage.py syncdb in /srv/smsBEST/gateway
* Put run_gateway.sh in /srv/smsBEST/bin
* Put smsBEST.conf in /etc/supervisor/conf.d

9
gateway/run_gateway.sh Executable file
View File

@ -0,0 +1,9 @@
#!/bin/bash
#
# Launch the router. Put this file in /srv/smsBEST/bin.
#
cd /srv/smsBEST
source bin/activate
cd gateway
python manage.py runrouter

197
gateway/settings.py Executable file
View File

@ -0,0 +1,197 @@
#!/usr/bin/env python
# vim: ai ts=4 sts=4 et sw=4
# encoding=utf-8
# -------------------------------------------------------------------- #
# MAIN CONFIGURATION #
# -------------------------------------------------------------------- #
# you should configure your database here before doing any real work.
# see: http://docs.djangoproject.com/en/dev/ref/settings/#databases
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": "rapidsms.sqlite3",
}
}
# the rapidsms backend configuration is designed to resemble django's
# database configuration, as a nested dict of (name, configuration).
#
# the ENGINE option specifies the module of the backend; the most common
# backend types (for a GSM modem or an SMPP server) are bundled with
# rapidsms, but you may choose to write your own.
#
# all other options are passed to the Backend when it is instantiated,
# to configure it. see the documentation in those modules for a list of
# the valid options for each.
INSTALLED_BACKENDS = {
"modem": {
"ENGINE": "rapidsms.backends.gsm",
"PORT": "/dev/ttyS0",
"baudrate": 115200,
"timeout": 10
},
#"verizon": {
# "ENGINE": "rapidsms.backends.gsm,
# "PORT": "/dev/ttyUSB1"
#},
"message_tester": {
"ENGINE": "rapidsms.backends.bucket",
}
}
GATEWAY = {
"backend": "modem",
"secret": "something secret",
"push": "http://chalobest.in:8086/?from=%(from)s&txt=%(txt)s&secret=%(secret)s"
}
AJAX_PROXY_HOST = "0.0.0.0" # to open the gateway from the outside
# to help you get started quickly, many django/rapidsms apps are enabled
# by default. you may wish to remove some and/or add your own.
INSTALLED_APPS = [
# the essentials.
"django_nose",
"djtables",
"rapidsms",
# common dependencies (which don't clutter up the ui).
"rapidsms.contrib.handlers",
"rapidsms.contrib.ajax",
# enable the django admin using a little shim app (which includes
# the required urlpatterns), and a bunch of undocumented apps that
# the AdminSite seems to explode without.
"django.contrib.sites",
"django.contrib.auth",
"django.contrib.admin",
"django.contrib.sessions",
"django.contrib.contenttypes",
# the rapidsms contrib apps.
# "rapidsms.contrib.default",
"rapidsms.contrib.export",
"rapidsms.contrib.httptester",
# "rapidsms.contrib.locations",
"rapidsms.contrib.messagelog",
"rapidsms.contrib.messaging",
"rapidsms.contrib.gateway",
# "rapidsms.contrib.registration",
# "rapidsms.contrib.scheduler",
# "rapidsms.contrib.echo",
]
# this rapidsms-specific setting defines which views are linked by the
# tabbed navigation. when adding an app to INSTALLED_APPS, you may wish
# to add it here, also, to expose it in the rapidsms ui.
RAPIDSMS_TABS = [
("rapidsms.contrib.messagelog.views.message_log", "Message Log"),
# ("rapidsms.contrib.registration.views.registration", "Registration"),
("rapidsms.contrib.messaging.views.messaging", "Messaging"),
# ("rapidsms.contrib.locations.views.locations", "Map"),
# ("rapidsms.contrib.scheduler.views.index", "Event Scheduler"),
("rapidsms.contrib.httptester.views.generate_identity", "Message Tester"),
]
# -------------------------------------------------------------------- #
# BORING CONFIGURATION #
# -------------------------------------------------------------------- #
# debug mode is turned on as default, since rapidsms is under heavy
# development at the moment, and full stack traces are very useful
# when reporting bugs. don't forget to turn this off in production.
DEBUG = TEMPLATE_DEBUG = True
# after login (which is handled by django.contrib.auth), redirect to the
# dashboard rather than 'accounts/profile' (the default).
LOGIN_REDIRECT_URL = "/"
# use django-nose to run tests. rapidsms contains lots of packages and
# modules which django does not find automatically, and importing them
# all manually is tiresome and error-prone.
TEST_RUNNER = "django_nose.NoseTestSuiteRunner"
# for some reason this setting is blank in django's global_settings.py,
# but it is needed for static assets to be linkable.
MEDIA_URL = "/static/"
# this is required for the django.contrib.sites tests to run, but also
# not included in global_settings.py, and is almost always ``1``.
# see: http://docs.djangoproject.com/en/dev/ref/contrib/sites/
SITE_ID = 1
# the default log settings are very noisy.
LOG_LEVEL = "DEBUG"
LOG_FILE = "rapidsms.log"
LOG_FORMAT = "[%(name)s]: %(message)s"
LOG_SIZE = 8192 # 8192 bits = 8 kb
LOG_BACKUPS = 256 # number of logs to keep
# these weird dependencies should be handled by their respective apps,
# but they're not, so here they are. most of them are for django admin.
TEMPLATE_CONTEXT_PROCESSORS = [
"django.core.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media",
"django.core.context_processors.request",
]
# template loaders load templates from various places.
# for djtables to work properly, the egg loader needs to be
# included, the others are fairly standard.
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
'django.template.loaders.eggs.Loader'
)
# -------------------------------------------------------------------- #
# HERE BE DRAGONS! #
# these settings are pure hackery, and will go away soon #
# -------------------------------------------------------------------- #
# these apps should not be started by rapidsms in your tests, however,
# the models and bootstrap will still be available through django.
TEST_EXCLUDED_APPS = [
"django.contrib.sessions",
"django.contrib.contenttypes",
"django.contrib.auth",
"rapidsms",
"rapidsms.contrib.ajax",
"rapidsms.contrib.httptester",
]
# the project-level url patterns
ROOT_URLCONF = "urls"
# since we might hit the database from any thread during testing, the
# in-memory sqlite database isn't sufficient. it spawns a separate
# virtual database for each thread, and syncdb is only called for the
# first. this leads to confusing "no such table" errors. We create
# a named temporary instance instead.
import os
import tempfile
import sys
if 'test' in sys.argv:
for db_name in DATABASES:
DATABASES[db_name]['TEST_NAME'] = os.path.join(
tempfile.gettempdir(),
"%s.rapidsms.test.sqlite3" % db_name)

5
gateway/smsBEST.conf Normal file
View File

@ -0,0 +1,5 @@
# this file goes in /etc/supervisor/conf.d
[program:smsBEST]
command=/srv/smsBEST/bin/run_gateway.sh
directory=/srv/smsBEST/var
autorestart=true

View File

@ -5,3 +5,5 @@
-e git+git://github.com/bit/django-extensions.git#egg=django_extensions -e git+git://github.com/bit/django-extensions.git#egg=django_extensions
#django_extensions #django_extensions
django-grappelli django-grappelli
-e git+git://github.com/schuyler/rapidsms.git#egg=rapidsms
-e git+git://github.com/schuyler/arrest.git#egg=arrest

0
smsBEST/__init__.py Normal file
View File

18
smsBEST/manage.py Executable file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env python
# vim: ai ts=4 sts=4 et sw=4
#import sys, os
from django.core.management import execute_manager
import settings
if __name__ == "__main__":
# project_root = os.path.abspath(
# os.path.dirname(__file__))
# path = os.path.join(project_root, "apps")
# sys.path.insert(0, path)
# sys.path.insert(0, project_root)
execute_manager(settings)

View File

56
smsBEST/mumbai/app.py Normal file
View File

@ -0,0 +1,56 @@
from rapidsms.apps.base import AppBase
import re
import arrest
MAX_MSG_LEN = 160
DIGIT = re.compile(r"\d{1,3}")
PUNCT = re.compile(r"[^\w\s]")
"""
STYLE = {
"start": "-* ",
"repeat": " -*- ",
"end": " *-"
}
"""
STYLE = {"start": "", "repeat": "; ", "end": ""}
ChaloBest = arrest.Client("http://chalobest.in/1.0")
class App(AppBase):
def handle(self, msg):
if DIGIT.search(msg.text):
routes = ChaloBest.routes(q=msg.text.replace(" ", ""))
if not routes:
msg.respond("Sorry, we found no route marked '%s'." % msg.text)
return
detail = ChaloBest.route[routes[0]]
stops = detail['stops']['features']
origin, dest = stops[0]['properties'], stops[-1]['properties']
origin_name, dest_name = origin['display_name'], dest['display_name']
origin_area, dest_area = PUNCT.sub('', origin['area']), PUNCT.sub('', dest['area'])
msg.respond("%s: %s (%s) to %s (%s)" % (
",".join(routes), origin_name, origin_area, dest_name, dest_area))
else:
features = ChaloBest.stops(q=msg.text)['features']
if not features:
msg.respond("Sorry, we found no stops like '%s'." % msg.text)
return
stops = []
for feat in features:
stop = feat['properties']
if stops and stop["official_name"] == stops[-1]["official_name"]:
stops[-1]["routes"] += ", " + stop["routes"]
else:
stops.append(stop)
response = STYLE["start"]
for stop in stops:
match = stop["official_name"] + ": " + stop["routes"]
if len(response) > len(STYLE["repeat"]): response += STYLE["repeat"]
response += match
if len(response) > MAX_MSG_LEN: break
if len(response) > MAX_MSG_LEN:
response = response[:MAX_MSG_LEN-(len(STYLE["end"])+4)] + "..."
response += STYLE["end"]
msg.respond(response)

1
smsBEST/mumbai/views.py Normal file
View File

@ -0,0 +1 @@
# Create your views here.

205
smsBEST/settings.py Normal file
View File

@ -0,0 +1,205 @@
#!/usr/bin/env python
# vim: ai ts=4 sts=4 et sw=4
# encoding=utf-8
# -------------------------------------------------------------------- #
# MAIN CONFIGURATION #
# -------------------------------------------------------------------- #
# you should configure your database here before doing any real work.
# see: http://docs.djangoproject.com/en/dev/ref/settings/#databases
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql_psycopg2",
"NAME": "smsbest",
}
}
# the rapidsms backend configuration is designed to resemble django's
# database configuration, as a nested dict of (name, configuration).
#
# the ENGINE option specifies the module of the backend; the most common
# backend types (for a GSM modem or an SMPP server) are bundled with
# rapidsms, but you may choose to write your own.
#
# all other options are passed to the Backend when it is instantiated,
# to configure it. see the documentation in those modules for a list of
# the valid options for each.
INSTALLED_BACKENDS = {
#"att": {
# "ENGINE": "rapidsms.backends.gsm",
# "PORT": "/dev/ttyUSB0"
#},
#"verizon": {
# "ENGINE": "rapidsms.backends.gsm,
# "PORT": "/dev/ttyUSB1"
#},
"atlas": {
"ENGINE": "rapidsms.backends.http",
"host": "0.0.0.0",
"port": 8086,
"gateway_url": "http://atlas.gnowledge.org:8001/gateway/send",
"params_outgoing": "secret=something+secret&to=%(phone_number)s&txt=%(message)s",
"params_incoming": "from=%(phone_number)s&txt=%(message)s"
},
"message_tester": {
"ENGINE": "rapidsms.backends.bucket",
}
}
# to help you get started quickly, many django/rapidsms apps are enabled
# by default. you may wish to remove some and/or add your own.
INSTALLED_APPS = [
# the essentials.
"django_nose",
"djtables",
"rapidsms",
# common dependencies (which don't clutter up the ui).
"rapidsms.contrib.handlers",
"rapidsms.contrib.ajax",
# enable the django admin using a little shim app (which includes
# the required urlpatterns), and a bunch of undocumented apps that
# the AdminSite seems to explode without.
"django.contrib.sites",
"django.contrib.auth",
"django.contrib.admin",
"django.contrib.sessions",
"django.contrib.contenttypes",
# the rapidsms contrib apps.
# "rapidsms.contrib.default",
# "rapidsms.contrib.export",
"rapidsms.contrib.httptester",
# "rapidsms.contrib.locations",
"rapidsms.contrib.messagelog",
"rapidsms.contrib.messaging",
"rapidsms.contrib.registration",
# "rapidsms.contrib.scheduler",
# "rapidsms.contrib.echo",
"mumbai"
]
# this rapidsms-specific setting defines which views are linked by the
# tabbed navigation. when adding an app to INSTALLED_APPS, you may wish
# to add it here, also, to expose it in the rapidsms ui.
RAPIDSMS_TABS = [
("rapidsms.contrib.messagelog.views.message_log", "Message Log"),
("rapidsms.contrib.registration.views.registration", "Registration"),
("rapidsms.contrib.messaging.views.messaging", "Messaging"),
# ("rapidsms.contrib.locations.views.locations", "Map"),
# ("rapidsms.contrib.scheduler.views.index", "Event Scheduler"),
("rapidsms.contrib.httptester.views.generate_identity", "Message Tester"),
]
# -------------------------------------------------------------------- #
# BORING CONFIGURATION #
# -------------------------------------------------------------------- #
# debug mode is turned on as default, since rapidsms is under heavy
# development at the moment, and full stack traces are very useful
# when reporting bugs. don't forget to turn this off in production.
DEBUG = TEMPLATE_DEBUG = True
# after login (which is handled by django.contrib.auth), redirect to the
# dashboard rather than 'accounts/profile' (the default).
LOGIN_REDIRECT_URL = "/"
# use django-nose to run tests. rapidsms contains lots of packages and
# modules which django does not find automatically, and importing them
# all manually is tiresome and error-prone.
TEST_RUNNER = "django_nose.NoseTestSuiteRunner"
# for some reason this setting is blank in django's global_settings.py,
# but it is needed for static assets to be linkable.
MEDIA_URL = "/static/"
# this is required for the django.contrib.sites tests to run, but also
# not included in global_settings.py, and is almost always ``1``.
# see: http://docs.djangoproject.com/en/dev/ref/contrib/sites/
SITE_ID = 1
# the default log settings are very noisy.
LOG_LEVEL = "DEBUG"
LOG_FILE = "rapidsms.log"
LOG_FORMAT = "[%(name)s]: %(message)s"
LOG_SIZE = 8192 # 8192 bits = 8 kb
LOG_BACKUPS = 256 # number of logs to keep
# these weird dependencies should be handled by their respective apps,
# but they're not, so here they are. most of them are for django admin.
TEMPLATE_CONTEXT_PROCESSORS = [
"django.core.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media",
"django.core.context_processors.request",
]
# template loaders load templates from various places.
# for djtables to work properly, the egg loader needs to be
# included, the others are fairly standard.
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
'django.template.loaders.eggs.Loader'
)
# -------------------------------------------------------------------- #
# HERE BE DRAGONS! #
# these settings are pure hackery, and will go away soon #
# -------------------------------------------------------------------- #
# these apps should not be started by rapidsms in your tests, however,
# the models and bootstrap will still be available through django.
TEST_EXCLUDED_APPS = [
"django.contrib.sessions",
"django.contrib.contenttypes",
"django.contrib.auth",
"rapidsms",
"rapidsms.contrib.ajax",
"rapidsms.contrib.httptester",
]
# the project-level url patterns
ROOT_URLCONF = "urls"
# import local_settings.py
try:
from local_settings import *
except:
pass
# since we might hit the database from any thread during testing, the
# in-memory sqlite database isn't sufficient. it spawns a separate
# virtual database for each thread, and syncdb is only called for the
# first. this leads to confusing "no such table" errors. We create
# a named temporary instance instead.
import os
import tempfile
import sys
if 'test' in sys.argv:
for db_name in DATABASES:
DATABASES[db_name]['TEST_NAME'] = os.path.join(
tempfile.gettempdir(),
"%s.rapidsms.test.sqlite3" % db_name)

37
smsBEST/urls.py Normal file
View File

@ -0,0 +1,37 @@
from django.conf.urls.defaults import *
from django.conf import settings
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
# Example:
# (r'^my-project/', include('my_project.foo.urls')),
# Uncomment the admin/doc line below to enable admin documentation:
# (r'^admin/doc/', include('django.contrib.admindocs.urls')),
(r'^admin/', include(admin.site.urls)),
# RapidSMS core URLs
(r'^account/', include('rapidsms.urls.login_logout')),
url(r'^$', 'rapidsms.views.dashboard', name='rapidsms-dashboard'),
# RapidSMS contrib app URLs
(r'^ajax/', include('rapidsms.contrib.ajax.urls')),
(r'^export/', include('rapidsms.contrib.export.urls')),
(r'^httptester/', include('rapidsms.contrib.httptester.urls')),
(r'^locations/', include('rapidsms.contrib.locations.urls')),
(r'^messagelog/', include('rapidsms.contrib.messagelog.urls')),
(r'^messaging/', include('rapidsms.contrib.messaging.urls')),
(r'^registration/', include('rapidsms.contrib.registration.urls')),
(r'^scheduler/', include('rapidsms.contrib.scheduler.urls')),
)
if settings.DEBUG:
urlpatterns += patterns('',
# helper URLs file that automatically serves the 'static' folder in
# INSTALLED_APPS via the Django static media server (NOT for use in
# production)
(r'^', include('rapidsms.urls.static_media')),
)