Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django-rest pagination with angularjs

I have an angularjs app working nicely with django-rest but have hit an issue by introducing pagination. I have a restservice and controller as per the below

// restservices.js
// API call for all images in an event
services.factory('ImageEvent', function ($resource) {
    return $resource(rest_api + '/rest/image/?event_id=:eventId&format=json', {}, {
        query: { method:'GET', params:{eventId:''}, isArray:true}
    })
}); 

// controllers.js
// all Images in an event
.controller('ImageEventCtrl', ['$scope', '$stateParams', 'ImageEvent', function($scope, $stateParams, ImageEvent) {
  $scope.images = ImageEvent.query({eventId: $stateParams.eventId}, function(images) {
  });
}])

this returns the following json

[
    {
        "id": 13,
        "title": "01-IMG_4953.JPG",
    },
    {
        "id": 14,
        "title": "02-IMG_4975.JPG",
    },
    {
        "id": 15,
        "title": "03-IMG_4997.JPG",
    }
]

However if I turn on django-rest pagination it returns the following json:

{

    "count": 3,
    "next": "/rest/image/?event_id=1&page=2",
    "previous": null,
    "results": 
    [

        {
            "id": 13,
            "title": "01-IMG_4953.JPG",
        },
        {
            "id": 14,
            "title": "02-IMG_4975.JPG",
        }
    ]

}

This change has caused the following console error and everything fails to work:

Error: [$resource:badcfg] Error in resource configuration. Expected response to contain an array but got an object

Changing the restservice to isArray:false has made no difference. Can my controller be re-written to cope with this and in a perfect world also expose the count, next and previous links?

Thanks

like image 315
thefoxbrain Avatar asked Oct 21 '22 05:10

thefoxbrain


1 Answers

Angular-ui has a pagination directive that I've used with Django Rest Framework before.

http://angular-ui.github.io/bootstrap/#/pagination

To load only X amount of items at a time I have done the following below. Note that I'm using the pagination to recreate the django admin feature in angular.

if request.GET.get('page'):   
    # Get the page number                     
    page = request.GET.get('page')

    # How many items per page to display                 
    per_page = data['admin_attrs']['list_per_page']        


    begin = (int(page) - 1) * per_page                     
    end = begin + per_page                                 

    objects = MODEL.objects.all()[begin:end]               

# Serializer for your corresponding itmes. This will grab the particular modelserializer                                                           
serializer = serializer_classes[MODEL._meta.object_name](  
    objects, fields=admin_attrs['list_display']            
)                                                          


data['objects'] = serializer.data                          
return Response(data)         

My angular code to keep track of page and also allow back button functionality and also update the URL:

modelDetails Factory gets generates the url with the correct page number from pagination

app.factory('modelDetails', function($http, $q){                          
    data = {content: null}                                                                                                         
    var dataFactory = {}                                                  
    dataFactory.getObjects = function (app, model, page){                 
        var deferred = $q.defer()                                         
        $http.get('api/admin/' + app + '/' + model + '/?page=' + page)    
            .success(function(result) {                                   
                deferred.resolve(result);                                 
            });                                                           
        return  deferred.promise                                          
    };                                                                    

    return dataFactory                                                    
});    



$scope.loadObjects = function () {                                                         
    modelDetails.getObjects(app, model, $scope.currentPage)                                
    .then(function (data){                                                                 
        $scope.headers = data.headers;                                                     
        $scope.admin_attrs = data.admin_attrs;                                             

        blank =  new Array()                                                               
        list_display = data.admin_attrs.list_display                                       

        $scope.objects = convertObjects(data.objects, list_display)                        
        $scope.numPerPage = data.admin_attrs.list_per_page                                 
        $scope.currentPage = $stateParams.p                                                
        $scope.maxSize = 20;                                                               
        $scope.bigTotalItems = data.object_count;                                          
        $scope.numPages = Math.ceil(data.object_count /                $scope.admin_attrs.list_per_page); 

    })                                                                                     
    .then( function (data) {                                                               

        $scope.$watch('currentPage + numPerPage', function(oldVal, newVal) {               
            var begin = (($scope.currentPage - 1) * $scope.numPerPage)                     
            , end = begin + $scope.numPerPage;                                             

            if(oldVal != newVal){                                                          
                $location.search('p', $scope.currentPage)                                  
            }                                                                              

            $rootScope.$on('$locationChangeSuccess', function(event) {                     
                $scope.currentPage = $location.search().p                                  
                    modelDetails.getObjects(app, model, $scope.currentPage)                
                        .then( function (data) {  
                            // convertObjects just reorders my data in a way I want                                         
                            $scope.objects = convertObjects(data.objects, list_display)    
                        });                                                                
            });                                                                            
        });                                                                                
     });                                                                                   
}                 
like image 69
Austin Avatar answered Oct 23 '22 15:10

Austin