Skip to content

Commit 15ef517

Browse files
committed
first version of property REST implemented with some tests
1 parent 5108f45 commit 15ef517

File tree

5 files changed

+255
-57
lines changed

5 files changed

+255
-57
lines changed

README

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
This django application provides a REST interface for saving, updating, querying and deleting geojson features.
1+
This django application provides a REST interface for saving, updating, querying and deleting geojson features.

geojson_rest/models.py

+12-6
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,22 @@ class Property(models.Model):
1616
1717
feature -- geographical feature that this property belong to
1818
user -- the user that added this property
19+
group -- the group the property belong to, should be the same as the
20+
features that the property might be connected to
1921
json_data -- foreignkey to the json data model
2022
time -- foreignkey to the time model
2123
"""
2224
user = models.ForeignKey(User)
23-
25+
group = models.CharField(default = '@self',
26+
max_length = 50)
27+
2428
json_data = models.OneToOneField(JSON)
2529
time = models.OneToOneField(TimeD)
2630

27-
def create(self, properties, user, *args, **kwargs):
31+
def create(self, properties, *args, **kwargs):
2832
"""
2933
This function saves properties of the feature,
3034
"""
31-
self.user = user
3235
js = JSON(json_string = json.dumps(properties),
3336
collection = 'properties')
3437
js.save()
@@ -51,7 +54,9 @@ def to_json(self):
5154
retval = self.json_data.json()
5255
retval.update({'time': {'create_time': self.time.create_time.isoformat(),
5356
'expire_time': exrtime},
54-
'user': self.user.username})
57+
'user': self.user.username,
58+
'id': self.id,
59+
'group': self.group })
5560
return retval
5661

5762
class Meta:
@@ -103,8 +108,9 @@ def create(self, feature, *args, **kwargs):
103108
timed = TimeD()
104109
timed.save()
105110
self.time = timed
106-
prop = Property()
107-
prop.create(feature['properties'], self.user)
111+
prop = Property(user = self.user,
112+
group = self.group)
113+
prop.create(feature['properties'])
108114
super(Feature, self).save(*args, **kwargs)
109115
self.properties.add(prop)
110116

geojson_rest/tests.py

+97-9
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ def setUp(self):
1515
self.client = Client()
1616

1717
#setup a testuser
18-
self.user1 = User.objects.create_user('user1','', 'passwd')
19-
self.user2 = User.objects.create_user('user2','', 'passwd')
20-
self.user3 = User.objects.create_user('user3','', 'passwd')
21-
self.user4 = User.objects.create_user('user4','', 'passwd')
18+
self.user1 = User.objects.create_user('user1', '', 'passwd')
19+
self.user2 = User.objects.create_user('user2', '', 'passwd')
20+
self.user3 = User.objects.create_user('user3', '', 'passwd')
21+
self.user4 = User.objects.create_user('user4', '', 'passwd')
2222

2323
self.base_feature = {
2424
'type': 'Feature',
@@ -52,10 +52,12 @@ def test_create_and_get_feature(self):
5252

5353
response_json = json.loads(response.content)
5454
#returned feature should include id
55-
self.assertContains(response,
56-
'"id"',
57-
count = 1,
58-
status_code = 201)
55+
response_dict = json.loads(response.content)
56+
self.assertTrue(response_dict.has_key('id'),
57+
'The response feature did not have a key')
58+
self.assertEquals(response.status_code,
59+
201,
60+
'The response was not a 201 created')
5961
self.assertTrue(response_json['private'],
6062
'The feature returned did not include a private key')
6163

@@ -200,6 +202,92 @@ def test_create_and_delete_feature(self):
200202
'the feature was not deleted')
201203

202204
def test_create_and_get_property(self):
205+
#login to the service
206+
self.client.login(username = 'user1',
207+
password = 'passwd')
208+
203209
#get not existing property
204-
pass
210+
response = self.client.get(reverse('prop') + '/@me/test_group/3/500')
211+
212+
self.assertEquals(response.status_code,
213+
404,
214+
"Querying a non existing feature did not return 404")
215+
216+
#create a feature with property to group @self and user @me
217+
new_feature = self.base_feature
218+
new_feature.update({'properties': {'first': False}})
219+
response = self.client.post(reverse('feat'),
220+
json.dumps(new_feature),
221+
content_type = 'application/json')
222+
self.assertEquals(response.status_code,
223+
201,
224+
"Creating a feature did not return a 201 created")
225+
feature_id = json.loads(response.content)['id']
226+
property_id = json.loads(response.content)['properties']['id']
227+
228+
#query property saved with feature
229+
response = self.client.get('%s/@me/@self/%i/%i' % (reverse('prop'),
230+
feature_id,
231+
property_id))
232+
self.assertEquals(response.status_code,
233+
200,
234+
"Querying a property did not return status code 200")
235+
self.assertEquals(json.loads(response.content)['group'],
236+
'@self',
237+
'The property did not belong to @self group')
238+
239+
240+
#create property without feature to group 'test_group'
241+
response = self.client.post(reverse('prop') + '/@me/test_group/@null',
242+
json.dumps({'key': 'first saved'}),
243+
content_type = 'application/json')
244+
self.assertEquals(response.status_code,
245+
201,
246+
"Creating a property did not return a 201 created")
247+
248+
property_id = json.loads(response.content)['id']
249+
250+
#query property saved without feature
251+
response = self.client.get('%s/@me/test_group/@null/%i' % (reverse('prop'),
252+
property_id))
253+
self.assertEquals(response.status_code,
254+
200,
255+
"Querying a property did not return status code 200")
256+
self.assertEquals(json.loads(response.content)['group'],
257+
'test_group',
258+
'The property did not belong to test_group group')
259+
260+
#query all user1 properties
261+
response = self.client.get('%s/user1' % reverse('prop'))
262+
self.assertTrue(json.loads(response.content).has_key('totalResults'),
263+
'The returned collection did not have key totalResults')
264+
self.assertTrue(json.loads(response.content).has_key('entry'),
265+
'The returned collection did not have key entry')
266+
267+
#update property
268+
update_to_values = {'hello': 'world'}
269+
response = self.client.put('%s/@me/test_group/@null/%i' % (reverse('prop'),
270+
property_id),
271+
json.dumps(update_to_values),
272+
content_type = "application/json"
273+
)
274+
275+
self.assertTrue(json.loads(response.content).has_key('hello'),
276+
'A key was not found in updated property')
277+
278+
#delete property
279+
response = self.client.delete('%s/@me/test_group/@null/%i' % (reverse('prop'),
280+
property_id))
281+
282+
self.assertEquals(response.status_code,
283+
200,
284+
'Deleting a feature did not return 200 OK')
285+
286+
#get property and check that it does not exist
287+
response = self.client.get('%s/@me/test_group/@null/%i' % (reverse('prop'),
288+
property_id))
289+
290+
self.assertEquals(response.status_code,
291+
404,
292+
'Querying a deleted property did not return not found')
205293

geojson_rest/urls.py

+27-27
Original file line numberDiff line numberDiff line change
@@ -6,39 +6,39 @@
66

77
urlpatterns = patterns('geojson_rest.views',
88

9-
url(r'^feat$',
10-
FeatureView.as_view(),
11-
{'user': '@me',
12-
'group': '@self'},
13-
name="feat"),
9+
url(r'^feat$',
10+
FeatureView.as_view(),
11+
{'user': '@me',
12+
'group': '@self'},
13+
name="feat"),
1414

15-
(r'^feat/(?P<user>@?[-+_\w\.]+)$',
16-
FeatureView.as_view(),
17-
{'group': '@self'}),
15+
(r'^feat/(?P<user>@?[-+_\w\.]+)$',
16+
FeatureView.as_view(),
17+
{'group': '@self'}),
1818

19-
(r'^feat/(?P<user>@?[-+_\w\.]+)/(?P<group>@?[-+_\w]+)$',
20-
FeatureView.as_view()),
19+
(r'^feat/(?P<user>@?[-+_\w\.]+)/(?P<group>@?[-+_\w]+)$',
20+
FeatureView.as_view()),
2121

22-
(r'^feat/(?P<user>@?[-+_\w\.]+)/(?P<group>@?[-+_\w]+)/(?P<feature>@?\d+)$',
23-
FeatureView.as_view()),
22+
(r'^feat/(?P<user>@?[-+_\w\.]+)/(?P<group>@?[-+_\w]+)/(?P<feature>@?\d+)$',
23+
FeatureView.as_view()),
2424

25-
url(r'^prop$',
26-
PropertyView.as_view(),
27-
{'user': '@me',
28-
'group': '@self'},
29-
name="prop"),
25+
url(r'^prop$',
26+
PropertyView.as_view(),
27+
{'user': '@me',
28+
'group': '@self'},
29+
name="prop"),
3030

31-
(r'^prop/(?P<user>@?[-+_\w\.]+)$',
32-
PropertyView.as_view(),
33-
{'group': '@self'}),
31+
(r'^prop/(?P<user>@?[-+_\w\.]+)$',
32+
PropertyView.as_view(),
33+
{'group': '@self'}),
3434

35-
(r'^prop/(?P<user>@?[-+_\w\.]+)/(?P<group>@?[-+_\w]+)$',
36-
PropertyView.as_view()),
35+
(r'^prop/(?P<user>@?[-+_\w\.]+)/(?P<group>@?[-+_\w]+)$',
36+
PropertyView.as_view()),
3737

38-
(r'^prop/(?P<user>@?[-+_\w\.]+)/(?P<group>@?[-+_\w]+)/(?P<feature>@?\d+)$',
39-
PropertyView.as_view()),
38+
(r'^prop/(?P<user>@?[-+_\w\.]+)/(?P<group>@?[-+_\w]+)/(?P<feature>@?\d+|@null)$',
39+
PropertyView.as_view()),
4040

41-
(r'^prop/(?P<user>@?[-+_\w\.]+)/(?P<group>@?[-+_\w]+)/(?P<feature>@?\d+|@null)/(?P<property>@?\d+)$',
42-
PropertyView.as_view()),
41+
(r'^prop/(?P<user>@?[-+_\w\.]+)/(?P<group>@?[-+_\w]+)/(?P<feature>@?\d+|@null)/(?P<property>@?\d+)$',
42+
PropertyView.as_view()),
4343

44-
)
44+
)

0 commit comments

Comments
 (0)