Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

change urmobile URLs to 'mobile'

  • Loading branch information...
commit d15d156f75a4e31f50bafff154132ef3c69a7c45 1 parent f110183
Jennifer Bell authored April 11, 2010
2  .project
... ...
@@ -1,6 +1,6 @@
1 1
 <?xml version="1.0" encoding="UTF-8"?>
2 2
 <projectDescription>
3  
-	<name>fixmystreet google code</name>
  3
+	<name>FixMySteet</name>
4 4
 	<comment></comment>
5 5
 	<projects>
6 6
 	</projects>
117  mainapp/fixtures/test_rest.json
... ...
@@ -0,0 +1,117 @@
  1
+[
  2
+    {
  3
+        "pk": 1, 
  4
+        "model": "mainapp.report", 
  5
+        "fields": {
  6
+            "category": 5, 
  7
+            "is_hate": false, 
  8
+            "sent_at": "2009-02-02 16:58:06", 
  9
+            "is_confirmed": true, 
  10
+            "title": "Unfixed 1", 
  11
+            "photo": "", 
  12
+            "created_at": "2009-02-02 16:47:06", 
  13
+            "point": "POINT (-75.6965517998000053 45.4187415580000007)", 
  14
+            "updated_at": "2010-02-02 16:47:06", 
  15
+            "email_sent_to": "jennifer@visiblegovernment.ca", 
  16
+            "author": "Jennifer Bell", 
  17
+            "fixed_at": null, 
  18
+            "reminded_at": "2009-02-02 16:47:06", 
  19
+            "ward": 3, 
  20
+            "is_fixed": false, 
  21
+            "desc": "Here's a description with a lot of 'escapes' in it.\r\n\r\nAnd linebreaks!"
  22
+        }
  23
+    }, 
  24
+ 
  25
+    {
  26
+        "pk": 2, 
  27
+        "model": "mainapp.report", 
  28
+        "fields": {
  29
+            "category": 1, 
  30
+            "is_hate": false, 
  31
+            "sent_at": "2009-02-02 16:58:06", 
  32
+            "is_confirmed": true, 
  33
+            "title": "Unfixed 2", 
  34
+            "photo": "", 
  35
+            "created_at": "2009-02-02 16:47:06", 
  36
+            "point": "POINT (-75.6965517998000053 45.4187415580000007)", 
  37
+            "updated_at": "2010-02-02 16:47:06", 
  38
+            "email_sent_to": "jennifer@visiblegovernment.ca", 
  39
+            "author": "Jennifer Bell", 
  40
+            "fixed_at": null, 
  41
+            "reminded_at": "2009-02-02 16:47:06", 
  42
+            "ward": 3, 
  43
+            "is_fixed": false, 
  44
+            "desc": "Here's a description with a lot of 'escapes' in it.\r\n\r\nAnd linebreaks!"
  45
+        }
  46
+    }, 
  47
+
  48
+    {
  49
+        "pk": 3, 
  50
+        "model": "mainapp.report", 
  51
+        "fields": {
  52
+            "category": 1, 
  53
+            "is_hate": false, 
  54
+            "sent_at": "2009-02-02 16:58:06", 
  55
+            "is_confirmed": true, 
  56
+            "title": "Fixed in Two Days", 
  57
+            "photo": "", 
  58
+            "created_at": "2009-02-02 16:47:06", 
  59
+            "point": "POINT (-75.6824648380000014 45.4301269580000024)", 
  60
+            "updated_at": "2009-02-02 16:47:06", 
  61
+            "email_sent_to": "jennifer@visiblegovernment.ca", 
  62
+            "author": "Jennifer Bell", 
  63
+            "fixed_at": "2009-02-04 16:58:06", 
  64
+            "reminded_at": "2009-02-02 16:47:06", 
  65
+            "ward": 3, 
  66
+            "is_fixed": true, 
  67
+            "desc": "Here's a description with a lot of 'escapes' in it.\r\n\r\nAnd linebreaks!"
  68
+        }
  69
+    }, 
  70
+
  71
+    {
  72
+        "pk": 4, 
  73
+        "model": "mainapp.report", 
  74
+        "fields": {
  75
+            "category": 5, 
  76
+            "is_hate": false, 
  77
+            "sent_at": "2009-02-02 15:18:43", 
  78
+            "is_confirmed": true, 
  79
+            "title": "Fixed in 16 Days", 
  80
+            "photo": "", 
  81
+            "created_at": "2009-02-02 15:11:49", 
  82
+            "point": "POINT (-75.6824648380000014 45.4301269580000024)", 
  83
+            "updated_at": "2009-02-09 19:35:16", 
  84
+            "email_sent_to": "jennifer@visiblegovernment.ca", 
  85
+            "author": "Jennifer Bell", 
  86
+            "fixed_at": "2009-02-18 19:35:16", 
  87
+            "reminded_at": "2009-02-02 15:11:49", 
  88
+            "ward": 4, 
  89
+            "is_fixed": true, 
  90
+            "desc": "Parks!"
  91
+        }
  92
+    },
  93
+
  94
+    {
  95
+        "pk": 5, 
  96
+        "model": "mainapp.report", 
  97
+        "fields": {
  98
+            "category": 5, 
  99
+            "is_hate": false, 
  100
+            "sent_at": "2009-02-02 15:18:43", 
  101
+            "is_confirmed": false, 
  102
+            "title": "Fixed in 16 Days", 
  103
+            "photo": "", 
  104
+            "created_at": "2009-02-02 15:11:49", 
  105
+            "point": "POINT (-75.6824648380000014 45.4301269580000024)", 
  106
+            "updated_at": "2009-02-09 19:35:16", 
  107
+            "email_sent_to": "jennifer@visiblegovernment.ca", 
  108
+            "author": "Jennifer Bell", 
  109
+            "fixed_at": "2009-02-18 19:35:16", 
  110
+            "reminded_at": "2009-02-02 15:11:49", 
  111
+            "ward": 4, 
  112
+            "is_fixed": false, 
  113
+            "desc": "Parks!"
  114
+        }
  115
+    }
  116
+   
  117
+]
28  mainapp/models.py
@@ -266,7 +266,12 @@ class ReportUpdate(models.Model):
266 266
     phone = models.CharField(max_length=255, verbose_name = ugettext_lazy("Phone") )
267 267
     first_update = models.BooleanField(default=False)
268 268
     
269  
-    def send_emails(self):
  269
+    def notify(self):
  270
+        """
  271
+        Tell whoever cares that there's been an update to this report.
  272
+         -  If it's the first update, tell city officials
  273
+         -  Anything after that, tell subscribers
  274
+        """
270 275
         if self.first_update:
271 276
             self.notify_on_new()
272 277
         else:
@@ -318,6 +323,15 @@ def notify_on_update(self):
318 323
 
319 324
             
320 325
     def save(self):
  326
+        # does this update require confirmation?
  327
+        if not self.is_confirmed:
  328
+            self.get_confirmation()
  329
+        else:
  330
+            self.notify()
  331
+            
  332
+            
  333
+    def get_confirmation(self):
  334
+        """ Send a confirmation email to the user. """        
321 335
         if not self.confirm_token or self.confirm_token == "":
322 336
             m = md5.new()
323 337
             m.update(self.email)
@@ -345,7 +359,7 @@ class Meta:
345 359
 
346 360
 class ReportSubscriber(models.Model):
347 361
     """ 
348  
-        Report Subscribers are notified when there's an update.
  362
+        Report Subscribers are notified when there's an update to an existing report.
349 363
     """
350 364
     
351 365
     report = models.ForeignKey(Report)    
@@ -435,17 +449,15 @@ def __init__(self,ward, reports = []):
435 449
 
436 450
 class CityMap(GoogleMap):
437 451
     """
438  
-        Show all wards in a city as overlays.
  452
+        Show all wards in a city as overlays.  Used when debugging maps for new cities.
439 453
     """
440 454
     
441 455
     def __init__(self,city):
442 456
         polygons = []
443  
-        kml_url = 'http://localhost:8000/media/kml/' + city.name + '.kml'
444  
-
445 457
         ward = Ward.objects.filter(city=city)[:1][0]
446  
-        #for ward in Ward.objects.filter(city=city):
447  
-        #    for poly in ward.geom:
448  
-        #        polygons.append( GPolygon( poly ) )
  458
+        for ward in Ward.objects.filter(city=city):
  459
+            for poly in ward.geom:
  460
+                polygons.append( GPolygon( poly ) )
449 461
         GoogleMap.__init__(self,center=ward.geom.centroid,zoom=13,key=settings.GMAP_KEY, polygons=polygons, kml_urls=[kml_url],dom_id='map_canvas')
450 462
     
451 463
 
3  mainapp/tests/__init__.py
... ...
@@ -1,2 +1,3 @@
1 1
 from emailrules import *
2  
-from stats import *
  2
+from stats import *
  3
+from mobile import *
13  mainapp/tests/mobile.py
@@ -49,23 +49,23 @@ def get_json(self, query):
49 49
         return( simplejson.loads(response.content) )
50 50
         
51 51
     def test_get_by_query(self):
52  
-        result = self.get_json('/rest/reports.json?q=K2P1N8')
  52
+        result = self.get_json('/mobile/reports.json?q=K2P1N8')
53 53
         self.assertEquals( len(result), 4 )
54 54
         
55 55
     def test_get_bad_format(self):
56  
-        response = self.c.get('/rest/reports.unknown?q=K2P1N8')
  56
+        response = self.c.get('/mobile/reports.unknown?q=K2P1N8')
57 57
         self.assertEquals(response.status_code,415)
58 58
 
59 59
     def test_get_by_lat_lon(self):
60 60
         lon = '-75.6824648380000014'
61 61
         lat = '45.4301269580000024'
62  
-        result = self.get_json('/rest/reports.json?lat=%s;lon=%s' % (lat,lon))
  62
+        result = self.get_json('/mobile/reports.json?lat=%s;lon=%s' % (lat,lon))
63 63
         self.assertEquals( len(result), 4 )
64 64
 
65 65
     def test_get_by_lat_lon_with_r(self):
66 66
         lon = '-75.6824648380000014'
67 67
         lat = '45.4301269580000024'
68  
-        result = self.get_json('/rest/reports.json?lat=%s;lon=%s;r=.002' % (lat,lon))
  68
+        result = self.get_json('/mobile/reports.json?lat=%s;lon=%s;r=.002' % (lat,lon))
69 69
         self.assertEquals( len(result), 2 )
70 70
 
71 71
     def test_create_param_tranform(self):  
@@ -80,7 +80,7 @@ def test_create(self):
80 80
         m = md5.new( seed )
81 81
         params['api_key'] = binascii.b2a_base64(m.digest())
82 82
 
83  
-        response = self.c.post('/rest/reports.json', params )
  83
+        response = self.c.post('/mobile/reports.json', params )
84 84
         self.assertEquals( response.status_code, 200 )
85 85
         self.assertEqual(Report.objects.filter(title=params['title']).count(), 1 )
86 86
         # mail should go directly to the city.
@@ -89,9 +89,8 @@ def test_create(self):
89 89
         
90 90
     def test_create_no_nonce(self):
91 91
         params = MOBILE_PARAMS.copy()
92  
-        response = self.c.post('/rest/reports.json', params )
  92
+        response = self.c.post('/mobile/reports.json', params )
93 93
         self.assertEquals( response.status_code, 412 )
94  
-        print response.content
95 94
     
96 95
     def test_create_basecase(self):
97 96
         """
47  mainapp/views/main.py
... ...
@@ -1,6 +1,7 @@
1 1
 from django.shortcuts import render_to_response, get_object_or_404
2 2
 from django.http import HttpResponseRedirect
3 3
 from mainapp.models import Report, ReportUpdate, Ward, FixMyStreetMap, ReportCountQuery, City, FaqEntry, GoogleAddressLookup
  4
+from mainapp import search
4 5
 from django.template import Context, RequestContext
5 6
 from django.contrib.gis.measure import D 
6 7
 from django.contrib.gis.geos import *
@@ -13,7 +14,6 @@
13 14
 import urllib
14 15
 
15 16
 
16  
-
17 17
 def index(request, error_msg = None, disambiguate=None): 
18 18
     reports_with_photos = Report.objects.filter(is_confirmed=True).exclude(photo='').order_by("-created_at")[:3]
19 19
     recent_reports = Report.objects.filter(is_confirmed=True).order_by("-created_at")[:5]
@@ -27,43 +27,38 @@ def index(request, error_msg = None, disambiguate=None):
27 27
                  'disambiguate':disambiguate },
28 28
                 context_instance=RequestContext(request))    
29 29
 
30  
-
31 30
 def search_address(request):
32 31
     if request.method == 'POST':
33 32
         address = iri_to_uri(u'/search?q=%s' % request.POST["q"])
34 33
         return HttpResponseRedirect( address )
35  
-#        address = urllib.urlencode({'x':urlquote(request.POST["q"])})[2:]
36  
-#        return HttpResponseRedirect("/search?q=" + address )
37 34
 
38  
-    address = request.GET["q"] 
39  
-    address_lookup = GoogleAddressLookup( address )
  35
+    address = request.GET["q"]
40 36
 
41  
-    if not address_lookup.resolve():
42  
-        return index(request, _("Sorry, we couldn\'t retreive the coordinates of that location, please use the Back button on your browser and try something more specific or include the city name at the end of your search."))
43  
-    
44  
-    if not address_lookup.exists():
45  
-        return index( request, _("Sorry, we couldn\'t find the address you entered.  Please try again with another intersection, address or postal code, or add the name of the city to the end of the search."))
  37
+    match_index = -1
  38
+    if request.GET.has_key("index"):
  39
+        match_index = int(request.GET["index"] or 0)
46 40
 
47  
-    if address_lookup.matches_multiple() and not request.GET.has_key("index"):
48  
-        addrs = address_lookup.get_match_options() 
49  
-        addr_list = "" 
  41
+    addrs = []
  42
+    try:
  43
+        point_str = search.search_address(address, match_index, addrs)
  44
+    except search.SearchAddressDisambiguateError, e:
  45
+        # addrs = address_lookup.get_match_options()
  46
+        addr_list = ""
50 47
         for i in range(0,len(addrs)):
51 48
             link = "/search?q=" + urlquote(address) + "&index=" + str(i)
52 49
             addr_list += "<li><a href='%s'>%s</a></li>" % ( link, addrs[i] )
53 50
             addr_list += "</ul>"
54 51
         return index(request,disambiguate = addr_list )
55  
-    
56  
-    # otherwise, we have a specific match
57  
-    match_index = 0
58  
-    if request.GET.has_key("index"):
59  
-        match_index = int(request.GET["index"])
60  
-            
61  
-    point_str = "POINT(" + address_lookup.lon(match_index) + " " + address_lookup.lat(match_index) + ")"
62  
-    pnt = fromstr(point_str, srid=4326)    
63  
-    wards = Ward.objects.filter(geom__contains=point_str)
64  
-    if (len(wards) == 0):
65  
-        return( index(request, _("Sorry, we don't yet have that area in our database.  Please have your area councillor contact fixmystreet.ca.")))
66  
-    
  52
+    except search.SearchAddressException, e:
  53
+        return index(request, _(str(e)))
  54
+
  55
+    pnt = fromstr(point_str, srid=4326)
  56
+
  57
+    try:
  58
+        wards = search.search_wards(point_str)
  59
+    except search.SearchAddressNotSupported, e:
  60
+        return( index(request, _(str(e))))
  61
+
67 62
     reports = Report.objects.filter(is_confirmed = True,point__distance_lte=(pnt,D(km=4))).distance(pnt).order_by('distance')
68 63
     gmap = FixMyStreetMap(pnt,True,reports)
69 64
         
203  mainapp/views/mobile.py
@@ -3,14 +3,110 @@
3 3
 from django.contrib.gis.geos import fromstr
4 4
 from django.contrib.gis.measure import D
5 5
 from django.forms.util import ErrorDict
6  
-
7  
-from mainapp.models import Report
  6
+from mainapp.models import Report,ReportCategory
8 7
 from mainapp import search
  8
+from mainapp.views.reports.main import create_report
  9
+import md5
  10
+import binascii
  11
+import settings
  12
+from django.core import serializers
  13
+from django.http import HttpResponse, HttpResponseBadRequest
  14
+from django.db import models
9 15
 
10 16
 
11 17
 class InputValidationException(Exception):
12 18
     pass
13 19
 
  20
+class InvalidAPIKey(Exception):
  21
+    pass
  22
+
  23
+class MobileReportAPI(object):
  24
+    
  25
+    EXPOSE_FIELDS = ('id','point', 'title','desc','author','email_sent_to','created_at','is_fixed')
  26
+
  27
+    FORIEGN_TO_LOCAL_KEYS = {    'customer_email':'email',
  28
+                                 'customer_phone':'phone',
  29
+                                 'description': 'desc',
  30
+                                 'category': 'category_id'
  31
+                            }
  32
+    
  33
+    def get(self,request):
  34
+        ids = request.GET.getlist("id")
  35
+        if ids:
  36
+            try:
  37
+                ids = [int(id) for id in ids]
  38
+            except (TypeError, ValueError), e:
  39
+                raise InputValidationException(str(e))
  40
+            reports = Report.objects.filter(id__in = ids)
  41
+            # process ids right now
  42
+        else:
  43
+            lon = request.GET.get("lon")
  44
+            lat = request.GET.get("lat")
  45
+            address = request.GET.get("q")
  46
+            if lat and lon:
  47
+                point_str = "POINT(%s %s)" %(lon, lat)
  48
+            elif address:
  49
+                addrs = []
  50
+                match_index = int(request.GET.get('index', -1))
  51
+                point_str = search.search_address(address, match_index, addrs)
  52
+            else:
  53
+                raise InputValidationException('Must supply either a `q`, `lat` `lon`, or a report `id`')
  54
+
  55
+            radius = float(request.GET.get('r', 4))
  56
+            pnt = fromstr(point_str, srid=4326)
  57
+            reports = Report.objects.filter(is_confirmed = True,point__distance_lte=(pnt,D(km=radius))).distance(pnt).order_by('distance')[:100]
  58
+            return( reports ) 
  59
+        
  60
+    def post(self,request):
  61
+        request.POST = MobileReportAPI._transform_params(request.POST)
  62
+
  63
+        if not request.POST.has_key('device_id'):
  64
+            raise InputValidationException('General Service Error: No device_id')
  65
+
  66
+        if not MobileReportAPI._nonce_ok(request):
  67
+            raise InvalidAPIKey('Invalid API Key')
  68
+ 
  69
+        # we're good.        
  70
+        report = create_report(request,True)
  71
+        if not report:
  72
+            # some issue with our form input.  Does this need to be more detailed?
  73
+            raise InputValidationException('General Service Error: bad input')
  74
+        return( Report.objects.filter(pk=report.id) )
  75
+    
  76
+    def make_response(self,format,models = [],fields= None,status=200):
  77
+        mimetype = 'application/%s'%format
  78
+        data = serializers.serialize(format, models, fields=fields)
  79
+        return HttpResponse(data,mimetype=mimetype,status=status)
  80
+    
  81
+    @staticmethod    
  82
+    def _nonce_ok(request):
  83
+        timestamp = request.POST.get('timestamp')
  84
+        email = request.POST.get('email')
  85
+        nonce = request.POST.get('api_key')
  86
+        seed = '%s:%s:%s' % ( email,timestamp,settings.MOBILE_SECURE_KEY )
  87
+        m = md5.new( seed )
  88
+        compare_nonce = binascii.b2a_base64(m.digest())
  89
+        return( compare_nonce == nonce)
  90
+    
  91
+    @staticmethod
  92
+    def _transform_params(params):
  93
+        for theirkey,ourkey in MobileReportAPI.FORIEGN_TO_LOCAL_KEYS.items():
  94
+            if params.has_key(theirkey):
  95
+                params[ ourkey ] = params[ theirkey ]
  96
+                del(params[theirkey])
  97
+        
  98
+        # combine first and last names.
  99
+        if params.has_key('first_name') or params.has_key('last_name'):
  100
+            if params.has_key('first_name') and params.has_key('last_name'):
  101
+                params['author'] = params.get('first_name') + " " + params.get('last_name')
  102
+            else:
  103
+                params['author'] = params.get('first_name',params.get('last_name'))
  104
+            del(params['first_name'])
  105
+            del(params['last_name'])
  106
+                
  107
+        return( params )
  108
+
  109
+
14 110
 class RestCollection(Collection):
15 111
     ''' Subclasses Collection to provide multiple responders '''
16 112
     def __init__(self, queryset, responders=None, **kwargs):
@@ -43,6 +139,11 @@ def __call__(self, request, format, *args, **kwargs):
43 139
             self.responder = self.responders[format]
44 140
             try:
45 141
                 return Collection.__call__(self, request, *args, **kwargs)
  142
+            except search.SearchAddressDisambiguateError, e:
  143
+                return self.responder.error(request, 412, ErrorDict({
  144
+                    'info': [str(e)],
  145
+                    'possible_addresses': addrs }))
  146
+
46 147
             except InputValidationException, e:
47 148
                 errors = ErrorDict({'info': [str(e)]})
48 149
                 error_code = 412
@@ -52,68 +153,54 @@ def __call__(self, request, format, *args, **kwargs):
52 153
                 {'info': ['Requested content type "%s" not available!' %format]})
53 154
         # Using the last used responder to return error
54 155
         return self.responder.error(request, error_code, errors)
  156
+    
55 157
 
  158
+class MobileReportRest(RestCollection):
56 159
 
57  
-class CreateReportApi(RestCollection):
58  
-
59  
-    def create(self, request, *args, **kwargs):
60  
-    #
61  
-    # Create a New Report
62  
-    #
63  
-        form = request.method == 'POST' and forms.ReportForm(request.POST) or forms.ReportForm()
64  
-        if request.method == 'POST' and form.is_valid():
65  
-            # lon = request.GET.get("lon")
66  
-            #lat = request.GET.get("lat")
67  
-            #address = request.GET.get("q")
68  
-
69  
-            #report = form.save()
70  
-            if report:
71  
-                return HttpResponseCreated(request, request.build_absolute_uri())
72  
-            return self.render('create.html', request, {'form': form})
73  
-
74  
-class ReportRest(RestCollection):
75  
-
  160
+    api = MobileReportAPI()
  161
+    
76 162
     def read(self, request):
77  
-        ids = request.GET.getlist("id")
78  
-        if ids:
79  
-            try:
80  
-                ids = [int(id) for id in ids]
81  
-            except (TypeError, ValueError), e:
82  
-                raise InputValidationException(str(e))
83  
-            reports = Report.objects.filter(id__in = ids)
84  
-            # process ids right now
85  
-        else:
86  
-            lon = request.GET.get("lon")
87  
-            lat = request.GET.get("lat")
88  
-            address = request.GET.get("q")
89  
-            if lat and lon:
90  
-                point_str = "POINT(%s %s)" %(lon, lat)
91  
-            elif address:
92  
-                addrs = []
93  
-                match_index = int(request.GET.get('index', -1))
94  
-                try:
95  
-                    point_str = search.search_address(address, match_index, addrs)
96  
-                except search.SearchAddressDisambiguateError, e:
97  
-                    return self.responder.error(request, 412, ErrorDict({
98  
-                        'info': [str(e)],
99  
-                        'possible_addresses': addrs }))
100  
-            else:
101  
-                raise InputValidationException('Must supply either a `q`, `lat` `lon`, or a report `id`')
  163
+        reports = self.api.get(request)
  164
+        return self.responder.list(request, reports)
102 165
 
103  
-            radius = float(request.GET.get('r', 4))
104  
-            pnt = fromstr(point_str, srid=4326)
105  
-            reports = Report.objects.filter(is_confirmed = True,point__distance_lte=(pnt,D(km=radius))).distance(pnt).order_by('distance')
  166
+    def create(self, request, *args, **kwargs):
  167
+        report = self.api.post(request)
  168
+        return self.responder.list(request, report )
106 169
 
107  
-        return self.responder.list(request, reports)
  170
+            
108 171
 
109  
-reports_rest = ReportRest(
  172
+# These use the django-rest-api library.
  173
+mobile_report_rest = MobileReportRest(
110 174
     queryset=Report.objects.all(),
111  
-    permitted_methods = ('GET', 'POST'),
112  
-#     expose_fields = ('id','point'),
  175
+    permitted_methods = ['GET', 'POST'],
  176
+    expose_fields = MobileReportAPI.EXPOSE_FIELDS
113 177
 )
114 178
 
115  
-report_create = CreateReportApi(
116  
-    queryset=Report.objects.all(),
117  
-    permitted_methods = ('GET', 'POST'),
118  
-#     expose_fields = ('id','point'),
119  
-)
  179
+json_poll_resource = Collection(
  180
+    queryset = ReportCategory.objects.all(),
  181
+    expose_fields = ('id', 'name_en', 'name_fr'),
  182
+    #permitted_methods = ('GET'),
  183
+    responder = JSONResponder()
  184
+)
  185
+
  186
+# These classes do not use the django-rest-api library
  187
+
  188
+class MobileReportAPIError(models.Model):
  189
+    EXPOSE_FIELDS = ('error',)
  190
+    error = models.CharField(max_length=255)
  191
+    
  192
+def mobile_reports( request, format ):
  193
+    api = MobileReportAPI()
  194
+    supported_formats = [ 'xml','json' ]
  195
+    if not format in supported_formats:
  196
+        return( HttpResponse('Requested content type "%s" not available.'%format,status=415))         
  197
+    try:
  198
+        if request.method == "POST":
  199
+            to_serialize = api.post(request)
  200
+        else:
  201
+            to_serialize = api.get(request) 
  202
+        return( api.make_response(format,to_serialize,MobileReportAPIError.EXPOSE_FIELDS ) )
  203
+    except Exception, e:
  204
+        to_serialize = [ MobileReportAPIError(error=str(e)) ]
  205
+        return( api.make_response(format,to_serialize,MobileReportAPIError.EXPOSE_FIELDS, status=412 ) )
  206
+ 
66  mainapp/views/reports/main.py
@@ -7,37 +7,51 @@
7 7
 from fixmystreet import settings
8 8
 from django.utils.translation import ugettext as _
9 9
 
  10
+def create_report( request, is_confirmed = False):
  11
+    """
  12
+        Helper method used by both internal and Open311 API.
  13
+    """
  14
+    pnt = fromstr("POINT(" + request.POST["lon"] + " " + request.POST["lat"] + ")", srid=4326)         
  15
+    update_form = ReportUpdateForm( request.POST  )   
  16
+    report_form = ReportForm( request.POST, request.FILES )
  17
+        
  18
+    # this is a lot more complicated than it has to be because of the information
  19
+    # spread across two forms.
  20
+        
  21
+    if request.POST['category_id'] != "" and update_form.is_valid() and report_form.is_valid():
  22
+        report = report_form.save( commit = False )
  23
+        update = update_form.save(commit=False)
  24
+        #these are in the form for 'update'
  25
+        report.desc = update.desc
  26
+        report.author = update.author
  27
+        #this is in neither form
  28
+        report.category_id = request.POST['category_id']
  29
+        #this info is custom
  30
+        report.point = pnt
  31
+        report.ward = Ward.objects.get(geom__contains=pnt)
  32
+        report.is_confirmed = is_confirmed
  33
+        update.report = report
  34
+        update.first_update = True
  35
+        update.is_confirmed = is_confirmed
  36
+        update.created_at = report.created_at
  37
+        report.save()
  38
+        report.reportupdate_set.add(update)
  39
+        report.save()
  40
+        return( report )
  41
+    else:
  42
+        return None
10 43
 
11 44
 def new( request ):
12 45
     category_error = None
13 46
 
14 47
     if request.method == "POST":
15  
-        pnt = fromstr("POINT(" + request.POST["lon"] + " " + request.POST["lat"] + ")", srid=4326)         
16  
-        f = request.POST.copy()
17  
-        update_form = ReportUpdateForm( {'email':request.POST['email'], 'desc':request.POST['desc'],
18  
-                                         'author':request.POST['author'], 'phone': request.POST['phone']})    
19  
-        report_form = ReportForm({'title' : request.POST['title']}, request.FILES )
20  
-        
21  
-        # this is a lot more complicated than it has to be because of the infortmation
22  
-        # spread across two records.
23  
-        
24  
-        if request.POST['category_id'] != "" and update_form.is_valid() and report_form.is_valid():
25  
-            report = report_form.save( commit = False )
26  
-            report.point = pnt
27  
-            report.category_id = request.POST['category_id']
28  
-            report.author = request.POST['author']
29  
-            report.desc = request.POST['desc']
30  
-            report.ward = Ward.objects.get(geom__contains=pnt)
31  
-            report.save()
32  
-            update = update_form.save(commit=False)
33  
-            update.report = report
34  
-            update.first_update = True
35  
-            update.created_at = report.created_at
36  
-            update.save()
37  
-            return( HttpResponseRedirect( report.get_absolute_url() ))
38  
-        
39  
-         # other form errors are handled by the form objects.
40  
-        if not request.POST['category_id']:
  48
+        # TOFIX:category ID is checked for separately as it's not part of the report form
  49
+        if request.POST['category_id']:
  50
+            report = create_report(request)
  51
+            if report:
  52
+                return( HttpResponseRedirect( report.get_absolute_url() ))
  53
+            # otherwise, there was an error with one of the forms.
  54
+        else:
41 55
             category_error = _("Please select a category")
42 56
             
43 57
     else:
10  mainapp/views/reports/updates.py
@@ -15,6 +15,13 @@ def new( request, report_id ):
15 15
             update.save()    
16 16
             # redirect after a POST       
17 17
             return( HttpResponseRedirect( '/reports/updates/create/' ) )
  18
+        else:
  19
+            print "update not valid"
  20
+            for field in update_form:
  21
+                if field.errors:
  22
+                    print str(field)
  23
+                    print field.errors
  24
+                
18 25
     else:
19 26
         update_form = ReportUpdateForm()
20 27
         
@@ -55,7 +62,6 @@ def confirm( request, confirm_token ):
55 62
         update.report.is_confirmed = True
56 63
  
57 64
     update.report.save()
58  
-    update.send_emails()
59  
-        
  65
+         
60 66
     # redirect to report    
61 67
     return( HttpResponseRedirect( update.report.get_absolute_url() ))
19  urls.py
@@ -85,24 +85,11 @@
85 85
 
86 86
 # REST Urls
87 87
 rest_format = r'(?P<format>\w+)'
88  
-urlpatterns += patterns('mainapp.views.rest',
89  
-   url(r'^rest/reports.%s$'%rest_format, 'reports_rest'),
  88
+urlpatterns += patterns('mainapp.views.mobile',
  89
+   url(r'^mobile/reports.%s$'%rest_format, 'mobile_report_rest'),
  90
+   url(r'^mobile/categories/(.*?)/?$', 'json_poll_resource'),
90 91
 )
91 92
 
92  
-urlpatterns += patterns('mainapp.views.rest',
93  
-   url(r'^rest/report/create/$', 'report_create',name='create'),
94  
-)
95  
-
96  
-# Categories REST -- should move this to its rest.py
97  
-json_poll_resource = Collection(
98  
-    queryset = ReportCategory.objects.all(),
99  
-    expose_fields = ('id', 'name_en', 'name_fr'),
100  
-    #permitted_methods = ('GET'),
101  
-    responder = JSONResponder()
102  
-)
103  
-urlpatterns += patterns('mainapp.views.rest',
104  
-   url(r'^rest/categories/(.*?)/?$', json_poll_resource),
105  
-)
106 93
 
107 94
 #The following is used to serve up local media files like images
108 95
 #if settings.LOCAL_DEV:

0 notes on commit d15d156

Please sign in to comment.
Something went wrong with that request. Please try again.