forked from I2P_Developers/i2p.www
Implemented pagination for meetings and blog entries
This commit is contained in:
@@ -14,6 +14,7 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
import simplejson as json
|
import simplejson as json
|
||||||
|
|
||||||
|
from helpers import Pagination
|
||||||
|
|
||||||
TEMPLATE_DIR = os.path.join(os.path.dirname(__file__), 'pages')
|
TEMPLATE_DIR = os.path.join(os.path.dirname(__file__), 'pages')
|
||||||
STATIC_DIR = os.path.join(os.path.dirname(__file__), 'static')
|
STATIC_DIR = os.path.join(os.path.dirname(__file__), 'static')
|
||||||
@@ -21,6 +22,9 @@ STATIC_DIR = os.path.join(os.path.dirname(__file__), 'static')
|
|||||||
BLOG_DIR = os.path.join(os.path.dirname(__file__), 'blog')
|
BLOG_DIR = os.path.join(os.path.dirname(__file__), 'blog')
|
||||||
MEETINGS_DIR = os.path.join(os.path.dirname(__file__), 'meetings')
|
MEETINGS_DIR = os.path.join(os.path.dirname(__file__), 'meetings')
|
||||||
|
|
||||||
|
BLOG_ENTRIES_PER_PAGE = 20
|
||||||
|
MEETINGS_PER_PAGE = 20
|
||||||
|
|
||||||
MIRRORS_FILE = os.path.join(TEMPLATE_DIR, 'downloads/mirrors')
|
MIRRORS_FILE = os.path.join(TEMPLATE_DIR, 'downloads/mirrors')
|
||||||
|
|
||||||
app = application = Flask('i2p2www', template_folder=TEMPLATE_DIR, static_url_path='/_static', static_folder=STATIC_DIR)
|
app = application = Flask('i2p2www', template_folder=TEMPLATE_DIR, static_url_path='/_static', static_folder=STATIC_DIR)
|
||||||
@@ -141,7 +145,15 @@ def utility_processor():
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
# The I2P site has no known clearnet address, so use an inproxy
|
# The I2P site has no known clearnet address, so use an inproxy
|
||||||
return value + '.to'
|
return value + '.to'
|
||||||
return dict(i2pconv=convert_url_to_clearnet)
|
|
||||||
|
# Convert a paginated URL to that of another page
|
||||||
|
def url_for_other_page(page):
|
||||||
|
args = request.view_args.copy()
|
||||||
|
args['page'] = page
|
||||||
|
return url_for(request.endpoint, **args)
|
||||||
|
|
||||||
|
return dict(i2pconv=convert_url_to_clearnet,
|
||||||
|
url_for_other_page=url_for_other_page)
|
||||||
|
|
||||||
|
|
||||||
################
|
################
|
||||||
@@ -156,6 +168,15 @@ def server_error(error):
|
|||||||
return render_template('global/error_500.html'), 500
|
return render_template('global/error_500.html'), 500
|
||||||
|
|
||||||
|
|
||||||
|
########################
|
||||||
|
# General helper methods
|
||||||
|
|
||||||
|
def get_for_page(items, page, per_page):
|
||||||
|
from_item = (page-1)*per_page
|
||||||
|
to_item = page*per_page
|
||||||
|
return items[from_item:to_item]
|
||||||
|
|
||||||
|
|
||||||
#######################
|
#######################
|
||||||
# General page handlers
|
# General page handlers
|
||||||
|
|
||||||
@@ -267,9 +288,12 @@ def render_meeting_rst(id):
|
|||||||
@app.route('/<string:lang>/meetings/', defaults={'page': 1})
|
@app.route('/<string:lang>/meetings/', defaults={'page': 1})
|
||||||
@app.route('/<string:lang>/meetings/page/<int:page>')
|
@app.route('/<string:lang>/meetings/page/<int:page>')
|
||||||
def meetings_index(page):
|
def meetings_index(page):
|
||||||
meetings = get_meetings()
|
all_meetings = get_meetings()
|
||||||
|
meetings = get_for_page(all_meetings, page, MEETINGS_PER_PAGE)
|
||||||
return render_template('meetings/index.html', meetings=meetings)
|
if not meetings and page != 1:
|
||||||
|
abort(404)
|
||||||
|
pagination = Pagination(page, MEETINGS_PER_PAGE, len(all_meetings))
|
||||||
|
return render_template('meetings/index.html', pagination=pagination, meetings=meetings)
|
||||||
|
|
||||||
# Renderer for specific meetings
|
# Renderer for specific meetings
|
||||||
@app.route('/<string:lang>/meetings/<int:id>')
|
@app.route('/<string:lang>/meetings/<int:id>')
|
||||||
@@ -476,9 +500,12 @@ def render_blog_entry(slug):
|
|||||||
@app.route('/<string:lang>/blog/', defaults={'page': 1})
|
@app.route('/<string:lang>/blog/', defaults={'page': 1})
|
||||||
@app.route('/<string:lang>/blog/page/<int:page>')
|
@app.route('/<string:lang>/blog/page/<int:page>')
|
||||||
def blog_index(page):
|
def blog_index(page):
|
||||||
entries = get_blog_entries()
|
all_entries = get_blog_entries()
|
||||||
|
entries = get_for_page(all_entries, page, BLOG_ENTRIES_PER_PAGE)
|
||||||
return render_template('blog/index.html', entries=entries)
|
if not entries and page != 1:
|
||||||
|
abort(404)
|
||||||
|
pagination = Pagination(page, BLOG_ENTRIES_PER_PAGE, len(all_entries))
|
||||||
|
return render_template('blog/index.html', pagination=pagination, entries=entries)
|
||||||
|
|
||||||
@app.route('/<string:lang>/blog/entry/<path:slug>')
|
@app.route('/<string:lang>/blog/entry/<path:slug>')
|
||||||
def blog_entry(slug):
|
def blog_entry(slug):
|
||||||
|
32
i2p2www/helpers.py
Normal file
32
i2p2www/helpers.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
from math import ceil
|
||||||
|
|
||||||
|
class Pagination(object):
|
||||||
|
def __init__(self, page, per_page, total_count):
|
||||||
|
self.page = page
|
||||||
|
self.per_page = per_page
|
||||||
|
self.total_count = total_count
|
||||||
|
|
||||||
|
@property
|
||||||
|
def pages(self):
|
||||||
|
return int(ceil(self.total_count / float(self.per_page)))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def has_prev(self):
|
||||||
|
return self.page > 1
|
||||||
|
|
||||||
|
@property
|
||||||
|
def has_next(self):
|
||||||
|
return self.page < self.pages
|
||||||
|
|
||||||
|
def iter_pages(self, left_edge=2, left_current=2,
|
||||||
|
right_current=5, right_edge=2):
|
||||||
|
last = 0
|
||||||
|
for num in xrange(1, self.pages + 1):
|
||||||
|
if num <= left_edge or \
|
||||||
|
(num > self.page - left_current - 1 and \
|
||||||
|
num < self.page + right_current) or \
|
||||||
|
num > self.pages - right_edge:
|
||||||
|
if last + 1 != num:
|
||||||
|
yield None
|
||||||
|
yield num
|
||||||
|
last = num
|
@@ -10,4 +10,6 @@
|
|||||||
<li>{{ entry[1] }} - <a href="{{ url_for('blog_entry', slug=entry[0]) }}">{{ entry[2] }}</a></li>
|
<li>{{ entry[1] }} - <a href="{{ url_for('blog_entry', slug=entry[0]) }}">{{ entry[2] }}</a></li>
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
{%- from "global/macros" import render_pagination with context -%}
|
||||||
|
{{ render_pagination(pagination) | safe }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
{%- else -%}{{ url_for('site_show', lang=g.lang) }}
|
{%- else -%}{{ url_for('site_show', lang=g.lang) }}
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
{%- endmacro -%}
|
{%- endmacro -%}
|
||||||
|
|
||||||
{%- macro change_lang(lang) -%}
|
{%- macro change_lang(lang) -%}
|
||||||
{%- if request.endpoint == 'site_show' -%}{{ url_for('site_show', lang=lang, page=page) }}
|
{%- if request.endpoint == 'site_show' -%}{{ url_for('site_show', lang=lang, page=page) }}
|
||||||
{%- elif request.endpoint == 'blog_entry' -%}{{ url_for('blog_entry', lang=lang, slug=slug) }}
|
{%- elif request.endpoint == 'blog_entry' -%}{{ url_for('blog_entry', lang=lang, slug=slug) }}
|
||||||
@@ -12,8 +13,33 @@
|
|||||||
{%- else -%}{{ url_for('site_show', lang=lang) }}
|
{%- else -%}{{ url_for('site_show', lang=lang) }}
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
{%- endmacro -%}
|
{%- endmacro -%}
|
||||||
|
|
||||||
{%- macro ver(string=None) -%}
|
{%- macro ver(string=None) -%}
|
||||||
{%- if string -%}{{ string % '0.9.3' }}
|
{%- if string -%}{{ string % '0.9.3' }}
|
||||||
{%- else -%}{{ '0.9.3' }}
|
{%- else -%}{{ '0.9.3' }}
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
{%- endmacro -%}
|
{%- endmacro -%}
|
||||||
|
|
||||||
|
{%- macro render_pagination(pagination) %}
|
||||||
|
<div class="pagination">
|
||||||
|
{%- if pagination.has_prev %}
|
||||||
|
<a href="{{ url_for_other_page(pagination.page - 1)
|
||||||
|
}}">« Previous</a>
|
||||||
|
{%- endif %}
|
||||||
|
{%- for page in pagination.iter_pages() %}
|
||||||
|
{%- if page %}
|
||||||
|
{%- if page != pagination.page %}
|
||||||
|
<a href="{{ url_for_other_page(page) }}">{{ page }}</a>
|
||||||
|
{%- else %}
|
||||||
|
<strong>{{ page }}</strong>
|
||||||
|
{%- endif %}
|
||||||
|
{%- else %}
|
||||||
|
<span class="ellipsis">…</span>
|
||||||
|
{%- endif %}
|
||||||
|
{%- endfor %}
|
||||||
|
{%- if pagination.has_next %}
|
||||||
|
<a href="{{ url_for_other_page(pagination.page + 1)
|
||||||
|
}}">Next »</a>
|
||||||
|
{%- endif %}
|
||||||
|
</div>
|
||||||
|
{%- endmacro -%}
|
||||||
|
@@ -15,4 +15,6 @@
|
|||||||
<li><a href="{{ meeting_url(meeting['id']) }}">Meeting {{ meeting['id'] }}</a>{% if meeting['date'] %} - {{ meeting['date'].strftime("%B %d, %Y") }}{% endif %}</li>
|
<li><a href="{{ meeting_url(meeting['id']) }}">Meeting {{ meeting['id'] }}</a>{% if meeting['date'] %} - {{ meeting['date'].strftime("%B %d, %Y") }}{% endif %}</li>
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
{%- from "global/macros" import render_pagination with context -%}
|
||||||
|
{{ render_pagination(pagination) | safe }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
Reference in New Issue
Block a user