Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F81609216
pagination.py
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sat, Sep 7, 00:42
Size
4 KB
Mime Type
text/x-python
Expires
Mon, Sep 9, 00:42 (1 d, 23 h)
Engine
blob
Format
Raw Data
Handle
20600734
Attached To
R3600 invenio-infoscience
pagination.py
View Options
# -*- coding: utf-8 -*-
#
# This file is part of Invenio.
# Copyright (C) 2014 CERN.
#
# Invenio is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# Invenio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Invenio; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
"""Restful pagination."""
from
flask
import
request
,
url_for
from
invenio.utils.pagination
import
Pagination
as
InvenioPagination
from
.errors
import
InvalidPageError
class
RestfulPaginationMixIn
(
object
):
"""Provide implementaion methods :meth:`link_header` and :meth:`links`."""
def
link_header
(
self
,
**
kwargs
):
"""Return tuple that can be used in response header."""
links
=
self
.
links
(
**
kwargs
)
keys
=
(
"first"
,
"prev"
,
"next"
,
"last"
)
links_string
=
","
.
join
([
links
[
key
]
for
key
in
keys
if
key
in
links
])
return
(
'Link'
,
links_string
)
def
links
(
self
,
endpoint
=
None
,
args
=
None
):
"""Generate links for the headers.
:param endpoint: the URL endpoint
:param args: the arguments of request
:param count: the total number of items
"""
if
not
endpoint
:
endpoint
=
request
.
endpoint
if
not
args
:
args
=
request
.
args
links
=
{}
link_template
=
'<{}>; rel="{}"'
# arguments to stick to the URL
url_args
=
{}
# url_args['page'] will be updated for every link
url_args
[
'page'
]
=
1
url_args
[
'per_page'
]
=
self
.
per_page
# generate link for rel first
links
[
'first'
]
=
link_template
.
format
(
url_for
(
endpoint
,
**
url_args
),
"first"
)
# generate link for prev if it exists
if
self
.
has_prev
:
url_args
[
'page'
]
=
self
.
page
-
1
links
[
'prev'
]
=
link_template
.
format
(
url_for
(
endpoint
,
**
url_args
),
"prev"
)
# generate link for next if it exists
if
self
.
has_next
:
url_args
[
'page'
]
=
self
.
page
+
1
links
[
'next'
]
=
link_template
.
format
(
url_for
(
endpoint
,
**
url_args
),
"next"
)
# generate link for last
url_args
[
'page'
]
=
self
.
pages
links
[
'last'
]
=
link_template
.
format
(
url_for
(
endpoint
,
**
url_args
),
"last"
)
return
links
class
SQLAlchemyPaginationHelper
(
object
):
"""Wrap SQLAlchemy query `paginate` method."""
def
__init__
(
self
,
query
,
page
,
per_page
):
"""Initialize pagination property.
:param query: query object from SQLAlchemy
"""
self
.
query
=
query
self
.
page
=
page
self
.
per_page
=
per_page
self
.
pagination
=
self
.
query
.
paginate
(
self
.
page
,
self
.
per_page
,
False
)
class
RestfulSQLAlchemyPagination
(
SQLAlchemyPaginationHelper
,
RestfulPaginationMixIn
):
"""Implement Restful pagination for SQLAlchemy model."""
@property
def
items
(
self
):
"""Return found items."""
return
self
.
pagination
.
items
@property
def
pages
(
self
):
"""Return number of pages."""
return
self
.
pagination
.
pages
@property
def
has_next
(
self
):
"""Return `True` if has next page otherwise return `False`."""
return
self
.
pagination
.
has_next
@property
def
has_prev
(
self
):
"""Return `True` if has previous page otherwise return `False`."""
return
self
.
pagination
.
has_prev
class
RestfulPagination
(
InvenioPagination
,
RestfulPaginationMixIn
):
"""Implement Restful pagination for list of data."""
def
__init__
(
self
,
page
,
per_page
,
total_count
,
validate
=
True
):
super
(
RestfulPagination
,
self
)
.
__init__
(
page
,
per_page
,
total_count
)
if
validate
:
self
.
validate
()
def
validate
(
self
):
"""Validate the range of page and per_page."""
if
self
.
per_page
<
0
:
error_msg
=
(
"Invalid per_page argument ('{0}'). Number of items "
"per pages must be positive integer."
.
format
(
self
.
per_page
)
)
raise
InvalidPageError
(
error_msg
)
if
self
.
page
<
0
or
self
.
page
>
self
.
pages
:
error_msg
=
"Invalid page number ('{0}')."
.
format
(
self
.
page
)
raise
InvalidPageError
(
error_msg
)
def
slice
(
self
,
items
):
"""Return items on current page."""
return
items
[(
self
.
page
-
1
)
*
self
.
per_page
:
self
.
page
*
self
.
per_page
]
Event Timeline
Log In to Comment