david / django-portablecontacts (http://portablecontacts.net/)
Support for PortableContacts in Django.
Clone this repository (size: 65.7 KB): HTTPS / SSH
$ hg clone http://code.welldev.org/django-portablecontacts
| commit 2: | d759edee4b66 |
| parent 1: | 102195ccdbf9 |
| branch: | default |
Pagination, still a work in progress, a custom paginator is required.
21 months ago
Changed (Δ1.5 KB):
raw changeset »
portablecontacts/serializers/json.py (7 lines added, 6 lines removed)
portablecontacts/serializers/xml_serializer.py (4 lines added, 9 lines removed)
portablecontacts/tests.py (50 lines added, 30 lines removed)
portablecontacts/views.py (25 lines added, 5 lines removed)
Up to file-list portablecontacts/serializers/json.py:
| … | … | @@ -13,20 +13,21 @@ class Serializer(PythonSerializer): |
13 |
13 |
""" |
14 |
14 |
End serialization -- end the document. |
15 |
15 |
""" |
16 |
objects = { |
|
17 |
'entry': self.options.pop('for_self', False) and self.objects[0] or self.objects |
|
18 |
|
|
16 |
objects = {} |
|
19 |
17 |
if not self.options.pop('unique', False): |
20 |
18 |
objects.update({ |
21 |
19 |
'startIndex': self.options.pop('startIndex', 0), |
22 |
'totalResults': |
|
20 |
'totalResults': self.options.pop('totalResults', 0), |
|
23 |
21 |
}) |
24 |
if self.options.get(' |
|
22 |
if self.options.get('count', False): |
|
25 |
23 |
objects.update({ |
26 |
'itemsPerPage': self.options.pop(' |
|
24 |
'itemsPerPage': self.options.pop('count'), |
|
27 |
25 |
}) |
28 |
26 |
self.options.pop('stream', None) |
29 |
27 |
self.options.pop('fields', None) |
28 |
objects.update({ |
|
29 |
'entry': self.options.pop('for_self', False) and self.objects[0] or self.objects |
|
30 |
}) |
|
30 |
31 |
simplejson.dump(objects, self.stream, cls=DjangoJSONEncoder, **self.options) |
31 |
32 |
|
32 |
33 |
def getvalue(self): |
Up to file-list portablecontacts/serializers/xml_serializer.py:
| … | … | @@ -22,11 +22,11 @@ class Serializer(DjangoXMLSerializer): |
22 |
22 |
|
23 |
23 |
if not self.options.get('unique', False): |
24 |
24 |
self.indent(1) |
25 |
self.xml.addQuickElement("startIndex", s |
|
25 |
self.xml.addQuickElement("startIndex", str(self.options.get('startIndex', 0))) |
|
26 |
26 |
self.indent(1) |
27 |
self.xml.addQuickElement("itemsPerPage", s |
|
27 |
self.xml.addQuickElement("itemsPerPage", str(self.options.get('count', '0'))) |
|
28 |
28 |
self.indent(1) |
29 |
self.xml.addQuickElement("totalResults", s |
|
29 |
self.xml.addQuickElement("totalResults", str(self.options.get('totalResults', '0'))) |
|
30 |
30 |
|
31 |
31 |
def end_serialization(self): |
32 |
32 |
""" |
| … | … | @@ -58,12 +58,7 @@ class Serializer(DjangoXMLSerializer): |
58 |
58 |
if objects: |
59 |
59 |
name = convert_classname_to_name[rel_object.name] |
60 |
60 |
self.handle_reverse_fk_fields(objects, name) |
61 |
||
62 |
#if 'tags' in self._current: |
|
63 |
# self._current['tags'] = [tag['value'] for tag in self._current['tags']] |
|
64 |
#if 'relationships' in self._current: |
|
65 |
# self._current['relationships'] = [relationship['value'] \ |
|
66 |
# for relationship in self._current['relationships']] |
|
61 |
||
67 |
62 |
self.indent(1) |
68 |
63 |
self.xml.endElement("entry") |
69 |
64 |
Up to file-list portablecontacts/tests.py:
| … | … | @@ -245,6 +245,9 @@ data: |
245 |
245 |
200 |
246 |
246 |
>>> print response.content |
247 |
247 |
{ |
248 |
"itemsPerPage": 100, |
|
249 |
"startIndex": 0, |
|
250 |
"totalResults": 3, |
|
248 |
251 |
"entry": [ |
249 |
252 |
{ |
250 |
253 |
"displayName": "Minimal Contact", |
| … | … | @@ -278,7 +281,17 @@ data: |
278 |
281 |
"tags": [ |
279 |
282 |
"plaxo guy" |
280 |
283 |
], |
281 |
" |
|
284 |
"emails": [ |
|
285 |
{ |
|
286 |
"type": "work", |
|
287 |
"primary": true, |
|
288 |
"value": "mhashimoto-04@plaxo.com" |
|
289 |
}, |
|
290 |
{ |
|
291 |
"type": "home", |
|
292 |
"value": "mhashimoto-04@plaxo.com" |
|
293 |
} |
|
294 |
], |
|
282 |
295 |
"photos": [ |
283 |
296 |
{ |
284 |
297 |
"type": "thumbnail", |
| … | … | @@ -307,17 +320,7 @@ data: |
307 |
320 |
"value": "http://www.angryalien.com" |
308 |
321 |
} |
309 |
322 |
], |
310 |
"emails": [ |
|
311 |
{ |
|
312 |
"type": "work", |
|
313 |
"primary": true, |
|
314 |
"value": "mhashimoto-04@plaxo.com" |
|
315 |
}, |
|
316 |
{ |
|
317 |
"type": "home", |
|
318 |
"value": "mhashimoto-04@plaxo.com" |
|
319 |
} |
|
320 |
|
|
323 |
"id": 2, |
|
321 |
324 |
"addresses": [ |
322 |
325 |
{ |
323 |
326 |
"locality": "Springfield", |
| … | … | @@ -333,15 +336,13 @@ data: |
333 |
336 |
{ |
334 |
337 |
"preferredUsername": "david", |
335 |
338 |
"displayName": "David Larlet", |
339 |
"id": 3, |
|
336 |
340 |
"name": { |
337 |
341 |
"givenName": "David", |
338 |
342 |
"familyName": "Larlet" |
339 |
}, |
|
340 |
"id": 3 |
|
343 |
} |
|
341 |
344 |
} |
342 |
], |
|
343 |
"startIndex": 0, |
|
344 |
|
|
345 |
] |
|
345 |
346 |
} |
346 |
347 |
>>> response = c.get("/portablecontacts/@me/@all/1/") |
347 |
348 |
>>> response.status_code |
| … | … | @@ -380,8 +381,8 @@ XML representations:: |
380 |
381 |
<?xml version="1.0" encoding="utf-8"?> |
381 |
382 |
<response> |
382 |
383 |
<startIndex>0</startIndex> |
383 |
<itemsPerPage>0</itemsPerPage> |
|
384 |
<totalResults>0</totalResults> |
|
384 |
<itemsPerPage>100</itemsPerPage> |
|
385 |
<totalResults>3</totalResults> |
|
385 |
386 |
<entry> |
386 |
387 |
<id>1</id> |
387 |
388 |
<displayName>Minimal Contact</displayName> |
| … | … | @@ -463,18 +464,37 @@ XML representations:: |
463 |
464 |
<preferredUsername>david</preferredUsername> |
464 |
465 |
</entry> |
465 |
466 |
</response> |
466 |
>>> response = c.get("/portablecontacts/@me/@all/1/", {'format': 'xml'}) |
|
467 |
>>> response.status_code |
|
468 |
200 |
|
469 |
>>> print response.content |
|
470 |
<?xml version="1.0" encoding="utf-8"?> |
|
471 |
<response> |
|
472 |
<entry> |
|
473 |
<id>1</id> |
|
474 |
<displayName>Minimal Contact</displayName> |
|
475 |
</entry> |
|
476 |
</response> |
|
477 |
467 |
|
468 |
||
469 |
Pagination |
|
470 |
---------- |
|
471 |
||
472 |
Just the first entry:: |
|
473 |
||
474 |
>>> response = c.get("/portablecontacts/@me/@all/", {'startIndex':0, 'count':1}) |
|
475 |
>>> response.status_code |
|
476 |
200 |
|
477 |
>>> print response.content |
|
478 |
{ |
|
479 |
"itemsPerPage": 1, |
|
480 |
"startIndex": 0, |
|
481 |
"totalResults": 3, |
|
482 |
"entry": [ |
|
483 |
{ |
|
484 |
"displayName": "Minimal Contact", |
|
485 |
"id": 1 |
|
486 |
} |
|
487 |
] |
|
488 |
} |
|
489 |
||
490 |
And now entries 2 and 3:: |
|
491 |
||
492 |
>>> response = c.get("/portablecontacts/@me/@all/", {'startIndex':1, 'count':2}) |
|
493 |
>>> response.status_code |
|
494 |
200 |
|
495 |
>>> print response.content |
|
496 |
||
497 |
||
478 |
498 |
""" |
479 |
499 |
|
480 |
500 |
Up to file-list portablecontacts/views.py:
1 |
1 |
from django.conf import settings |
2 |
2 |
from django.core import serializers |
3 |
3 |
from django.http import HttpResponse |
4 |
from django.core.paginator import Paginator |
|
4 |
5 |
from django.core.urlresolvers import reverse |
5 |
6 |
|
6 |
7 |
from portablecontacts.utils import get_base_url, check_serializer, \ |
| … | … | @@ -11,14 +12,32 @@ def retrieve(request, id=None, format='j |
11 |
12 |
format = 'poco-%s' % request.GET.get('format', format) |
12 |
13 |
check_serializer(format) |
13 |
14 |
try: |
15 |
options = {'indent': True} |
|
14 |
16 |
if id is None: |
15 |
17 |
contacts = request.user.contact_set.all() |
16 |
|
|
18 |
# pagination |
|
19 |
startIndex = int(request.GET.get('startIndex', 0)) |
|
20 |
count = int(request.GET.get('count', 100)) |
|
21 |
paginator = Paginator(contacts, count) |
|
22 |
# Django pagination is by page and start at 1 |
|
23 |
# Portable contacts one is by element index and start at 0 |
|
24 |
if startIndex: |
|
25 |
# TODO: write a custom paginator based on indexes and not pages |
|
26 |
contacts = paginator.page(startIndex+1).object_list |
|
27 |
else: |
|
28 |
contacts = paginator.page(1).object_list |
|
29 |
options.update({ |
|
30 |
'unique': False, |
|
31 |
'startIndex': startIndex, |
|
32 |
'count': count, |
|
33 |
'totalResults': paginator.count, |
|
34 |
}) |
|
17 |
35 |
else: |
18 |
36 |
contacts = [contact_model.objects.get(id=id, user=request.user)] |
19 |
unique = True |
|
20 |
||
21 |
|
|
37 |
options.update({ |
|
38 |
'unique': True, |
|
39 |
}) |
|
40 |
response = serializers.serialize(format, contacts, **options) |
|
22 |
41 |
except contact_model.DoesNotExist: |
23 |
42 |
response = '' |
24 |
43 |
|
| … | … | @@ -31,7 +50,8 @@ def retrieve_self(request, format='json' |
31 |
50 |
contact = contact_model.objects.get( |
32 |
51 |
preferredUsername=request.user.username, |
33 |
52 |
user=request.user) |
34 |
|
|
53 |
options = {'indent': True, 'unique': True, 'for_self': True} |
|
54 |
response = serializers.serialize(format, [contact], **options) |
|
35 |
55 |
except contact_model.DoesNotExist: |
36 |
56 |
response = '' |
37 |
57 |
