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

Support for PortableContacts in Django.

Changed (Δ6.4 KB):

raw changeset »

portablecontacts/tests.py (256 lines added, 4 lines removed)

portablecontacts/views.py (6 lines added, 0 lines removed)

Up to file-list portablecontacts/tests.py:

@@ -465,11 +465,247 @@ XML representations::
465
465
       </entry>
466
466
      </response>
467
467
468
Sorting
469
-------
470
471
Sorting allows requests to specify the order in which contacts are returned.
472
473
sortBy, specifies the field name whose value SHALL be used to order the 
474
returned Contacts. The sort order is determine by the sortOrder parameter. 
475
If sortBy is a Singular Field, contacts are sorted according to that field's 
476
value; if it's a Plural Field, contacts are sorted by the Value 
477
(or Major Value, if it's a Complex Field) of the field marked with 
478
"primary": "true", if any, or else the first value in the list, if any, 
479
or else they are sorted last if the given contact has no data for the given 
480
field::
481
482
    >>> response = c.get("/portablecontacts/@me/@all/", {'sortBy': 'givenName'})
483
    >>> response.status_code
484
    200
485
    >>> print response.content
486
    {
487
     "itemsPerPage": 100, 
488
     "startIndex": 0, 
489
     "totalResults": 3, 
490
     "entry": [
491
      {
492
       "displayName": "Minimal Contact", 
493
       "id": 1
494
      }, 
495
      {
496
       "preferredUsername": "david", 
497
       "displayName": "David Larlet", 
498
       "id": 3, 
499
       "name": {
500
        "givenName": "David", 
501
        "familyName": "Larlet"
502
       }
503
      }, 
504
      {
505
       "relationships": [
506
        "friend"
507
       ], 
508
       "organizations": [
509
        {
510
         "name": "Burns Worldwide", 
511
         "title": "Head Bee Guy"
512
        }
513
       ], 
514
       "phoneNumbers": [
515
        {
516
         "type": "work", 
517
         "value": "KLONDIKE5"
518
        }, 
519
        {
520
         "type": "mobile", 
521
         "value": "650-123-4567"
522
        }
523
       ], 
524
       "displayName": "Mork Hashimoto", 
525
       "name": {
526
        "givenName": "Mork", 
527
        "familyName": "Hashimoto"
528
       }, 
529
       "tags": [
530
        "plaxo guy"
531
       ], 
532
       "emails": [
533
        {
534
         "type": "work", 
535
         "primary": true, 
536
         "value": "mhashimoto-04@plaxo.com"
537
        }, 
538
        {
539
         "type": "home", 
540
         "value": "mhashimoto-04@plaxo.com"
541
        }
542
       ], 
543
       "photos": [
544
        {
545
         "type": "thumbnail", 
546
         "value": "http://sample.site.org/photos/12345.jpg"
547
        }
548
       ], 
549
       "ims": [
550
        {
551
         "type": "aim", 
552
         "value": "plaxodev8"
553
        }
554
       ], 
555
       "accounts": [
556
        {
557
         "domain": "plaxo.com", 
558
         "userid": "2706"
559
        }
560
       ], 
561
       "urls": [
562
        {
563
         "type": "work", 
564
         "value": "http://www.seeyellow.com"
565
        }, 
566
        {
567
         "type": "home", 
568
         "value": "http://www.angryalien.com"
569
        }
570
       ], 
571
       "id": 2, 
572
       "addresses": [
573
        {
574
         "locality": "Springfield", 
575
         "country": "USA", 
576
         "region": "VT", 
577
         "formatted": "742 Evergreen Terrace\nSuite 123\nSpringfield VT 12345 USA", 
578
         "streetAddress": "742 Evergreen Terrace\nSuite 123", 
579
         "postalCode": "12345", 
580
         "type": "home"
581
        }
582
       ]
583
      }
584
     ]
585
    }
586
587
sortOrder, the order in which the sortBy parameter is applied. Allowed values 
588
are ascending and descending. If a value for sortBy is provided and no 
589
sortOrder is specifies, the sortOrder SHALL default to ascending. Sort order 
590
is expected to be case-insensitive Unicode alphabetic sort order, with no 
591
specific locale implied::
592
593
    >>> response = c.get("/portablecontacts/@me/@all/", {'sortBy': 'givenName', 'sortOrder': 'descending'})
594
    >>> response.status_code
595
    200
596
    >>> print response.content
597
    {
598
     "itemsPerPage": 100, 
599
     "startIndex": 0, 
600
     "totalResults": 3, 
601
     "entry": [
602
      {
603
       "relationships": [
604
        "friend"
605
       ], 
606
       "organizations": [
607
        {
608
         "name": "Burns Worldwide", 
609
         "title": "Head Bee Guy"
610
        }
611
       ], 
612
       "phoneNumbers": [
613
        {
614
         "type": "work", 
615
         "value": "KLONDIKE5"
616
        }, 
617
        {
618
         "type": "mobile", 
619
         "value": "650-123-4567"
620
        }
621
       ], 
622
       "displayName": "Mork Hashimoto", 
623
       "name": {
624
        "givenName": "Mork", 
625
        "familyName": "Hashimoto"
626
       }, 
627
       "tags": [
628
        "plaxo guy"
629
       ], 
630
       "emails": [
631
        {
632
         "type": "work", 
633
         "primary": true, 
634
         "value": "mhashimoto-04@plaxo.com"
635
        }, 
636
        {
637
         "type": "home", 
638
         "value": "mhashimoto-04@plaxo.com"
639
        }
640
       ], 
641
       "photos": [
642
        {
643
         "type": "thumbnail", 
644
         "value": "http://sample.site.org/photos/12345.jpg"
645
        }
646
       ], 
647
       "ims": [
648
        {
649
         "type": "aim", 
650
         "value": "plaxodev8"
651
        }
652
       ], 
653
       "accounts": [
654
        {
655
         "domain": "plaxo.com", 
656
         "userid": "2706"
657
        }
658
       ], 
659
       "urls": [
660
        {
661
         "type": "work", 
662
         "value": "http://www.seeyellow.com"
663
        }, 
664
        {
665
         "type": "home", 
666
         "value": "http://www.angryalien.com"
667
        }
668
       ], 
669
       "id": 2, 
670
       "addresses": [
671
        {
672
         "locality": "Springfield", 
673
         "country": "USA", 
674
         "region": "VT", 
675
         "formatted": "742 Evergreen Terrace\nSuite 123\nSpringfield VT 12345 USA", 
676
         "streetAddress": "742 Evergreen Terrace\nSuite 123", 
677
         "postalCode": "12345", 
678
         "type": "home"
679
        }
680
       ]
681
      }, 
682
      {
683
       "preferredUsername": "david", 
684
       "displayName": "David Larlet", 
685
       "id": 3, 
686
       "name": {
687
        "givenName": "David", 
688
        "familyName": "Larlet"
689
       }
690
      }, 
691
      {
692
       "displayName": "Minimal Contact", 
693
       "id": 1
694
      }
695
     ]
696
    }
697
468
698
469
699
Pagination
470
700
----------
471
701
472
Just the first entry::
702
The pagination parameters can be used together to "page through" a large 
703
number of results in manageable chunks.
704
705
For instance, on an initial query, specifying startIndex=0&count=1 will return 
706
only the first result. The total number of possible results is indicated by 
707
the totalResults field of results, so the client knows how many "pages" of 
708
results exist::
473
709
474
710
    >>> response = c.get("/portablecontacts/@me/@all/", {'startIndex':0, 'count':1})
475
711
    >>> response.status_code
@@ -487,13 +723,29 @@ Just the first entry::
487
723
     ]
488
724
    }
489
725
490
And now entries 2 and 3::
726
A subsequent query of startIndex=2&count=1 will return the next next result, 
727
and so on::
491
728
492
    >>> response = c.get("/portablecontacts/@me/@all/", {'startIndex':1, 'count':2})
729
    >>> response = c.get("/portablecontacts/@me/@all/", {'startIndex':2, 'count':1})
493
730
    >>> response.status_code
494
731
    200
495
732
    >>> print response.content
496
733
    {
734
     "itemsPerPage": 1, 
735
     "startIndex": 2, 
736
     "totalResults": 3, 
737
     "entry": [
738
      {
739
       "preferredUsername": "david", 
740
       "displayName": "David Larlet", 
741
       "id": 3, 
742
       "name": {
743
        "givenName": "David", 
744
        "familyName": "Larlet"
745
       }
746
      }
747
     ]
748
    }
497
749
   
498
750
"""
499
751

Up to file-list portablecontacts/views.py:

@@ -15,6 +15,12 @@ def retrieve(request, id=None, format='j
15
15
        options = {'indent': True}
16
16
        if id is None:
17
17
            contacts = request.user.contact_set.all()
18
            
19
            # sorting
20
            sortBy = request.GET.get('sortBy', 'id')
21
            sortOrder = request.GET.get('sortOrder', 'ascending')
22
            contacts = contacts.order_by('%s%s' % (sortOrder=='descending' and '-' or '', sortBy))
23
            
18
24
            # pagination
19
25
            startIndex = int(request.GET.get('startIndex', 0))
20
26
            count = int(request.GET.get('count', 100))