joshfriend/flask-restful-demo

Not able to paginate my restfull api because of error caused by functools.wraps

hussaintamboli opened this issue · 3 comments

I was following your code to put pagination in my Flask-Restful API.

def paginate(max_per_page=10):
    def decorator(func):
        @functools.wraps(func)
        def wrapped(*args, **kwargs):
            page = request.args.get('page', 1, type=int)
            per_page = min(request.args.get('per_page', max_per_page,
                                        type=int),
                       max_per_page)

            query = func(*args, **kwargs)
            p = query.paginate(page, per_page)

            meta = {
                'page': page,
                'per_page': per_page,
                'total': p.total,
                'pages': p.pages,
            }

            links = {}
            if p.has_next:
                links['next'] = url_for(request.endpoint, page=p.next_num,
                                    per_page=per_page, **kwargs)
            if p.has_prev:
                links['prev'] = url_for(request.endpoint, page=p.prev_num,
                                    per_page=per_page, **kwargs)
            links['first'] = url_for(request.endpoint, page=1,
                                 per_page=per_page, **kwargs)
            links['last'] = url_for(request.endpoint, page=p.pages,
                                per_page=per_page, **kwargs)

            meta['links'] = links
            result = {
                 'items': p.items,
                 'meta': meta
            }

            return result, 200
        return wrapped
    return decorator

class Users(Resource):

    @paginate
    def get(self):
        return 3

I am getting an error when I hit /api/users saying

Users object has no attribute '__name__'

I am not able to understand the issue. Can you help me out here please?

First observation is that the @paginate decorator expects a SQLAlchemy Query object to be returned from the view function. You are returning the integer 3.

It would help a ton if you could post the full stacktrace you get when running with app.debug = True.

Thanks for the prompt reply.

Users class has below code:

def get(self):
    args = self.validate_payload_and_return_args()
    data, status = self.process_the_request(args)
    return self.response(data, status)

def validate_payload_and_return_args(self):
    parser.add_argument('org_id', required=True, type=str, help="Org Id required")
    args = parser.parse_args()

    return args

@staticmethod
def response(response_dict, status_code=200):
    response = jsonify(response_dict)
    response.status_code = status_code
    return response

def process_the_request(self, params):

    org_id = params.get('org_id')

    recommended_jobs = session.query(Members)\
        .filter_by(org_id=org_id).all()

    return [dict(
        name=item.name
        created_on=item.created_on,
    ) for item in recommended_jobs], 200

And the stacktrace on the error is:

Traceback (most recent call last):
File "/home/hussain/venv-myapp/lib/python2.7/site-packages/flask/app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "/home/hussain/venv-myapp/lib/python2.7/site-packages/flask/app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/home/hussain/venv-myapp/lib/python2.7/site-packages/flask_cors/extension.py", line 110, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
File "/home/hussain/venv-myapp/lib/python2.7/site-packages/flask_restful/__init__.py", line 270, in error_router
return original_handler(e)
File "/home/hussain/venv-myapp/lib/python2.7/site-packages/flask_cors/extension.py", line 110, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
File "/home/hussain/venv-myapp/lib/python2.7/site-packages/flask/app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/hussain/venv-myapp/lib/python2.7/site-packages/flask_restful/__init__.py", line 267, in error_router
return self.handle_error(e)
File "/home/hussain/venv-myapp/lib/python2.7/site-packages/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/home/hussain/venv-myapp/lib/python2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/hussain/venv-myapp/lib/python2.7/site-packages/flask_cors/extension.py", line 110, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
File "/home/hussain/venv-myapp/lib/python2.7/site-packages/flask_restful/__init__.py", line 270, in error_router
return original_handler(e)
 File "/home/hussain/venv-myapp/lib/python2.7/site-packages/flask_cors/extension.py", line 110, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
File "/home/hussain/venv-myapp/lib/python2.7/site-packages/flask/app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/hussain/venv-myapp/lib/python2.7/site-packages/flask_restful/__init__.py", line 267, in error_router
return self.handle_error(e)
File "/home/hussain/venv-myapp/lib/python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "/home/hussain/venv-myapp/lib/python2.7/site-packages/flask/app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/hussain/venv-myapp/lib/python2.7/site-packages/flask_restful/__init__.py", line 462, in wrapper
resp = resource(*args, **kwargs)
File "/home/hussain/venv-myapp/lib/python2.7/site-packages/flask/views.py", line 84, in view
return self.dispatch_request(*args, **kwargs)
File "/home/hussain/venv-myapp/lib/python2.7/site-packages/flask_restful/__init__.py", line 572, in dispatch_request
resp = meth(*args, **kwargs)
File "/home/hussain/myapp/application/recruitment/resources/users.py", line 11, in decorator
@functools.wraps(func)
File "/usr/lib/python2.7/functools.py", line 33, in update_wrapper
setattr(wrapper, attr, getattr(wrapped, attr))
AttributeError: 'Users' object has no attribute '__name__'

Your Users class looks completely different now than in the initial issue description (@paginate disappeared?). You are still not returning a query object either. Looking at the stacktrace, I don't think the error happened anywhere in the stuff I wrote.