david / django-portablecontacts (http://portablecontacts.net/)

Support for PortableContacts in Django.

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': len(self.objects),
20
                'totalResults': self.options.pop('totalResults', 0),
23
21
            })
24
        if self.options.get('itemsPerPage', False):
22
        if self.options.get('count', False):
25
23
            objects.update({
26
                'itemsPerPage': self.options.pop('itemsPerPage', False),
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", self.options.get('startIndex', '0'))
25
            self.xml.addQuickElement("startIndex", str(self.options.get('startIndex', 0)))
26
26
            self.indent(1)
27
            self.xml.addQuickElement("itemsPerPage", self.options.get('itemsPerPage', '0'))
27
            self.xml.addQuickElement("itemsPerPage", str(self.options.get('count', '0')))
28
28
            self.indent(1)
29
            self.xml.addQuickElement("totalResults", self.options.get('totalResults', '0'))
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
         "id": 2, 
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
       "totalResults": 3
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
            unique = False
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
        response = serializers.serialize(format, contacts, indent=True, unique=unique)
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
        response = serializers.serialize(format, [contact], indent=True, unique=True, for_self=True)
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