Patch for pagination in static-rendering mode
Norman Yarvin <[email protected]> Fri, 16 Mar 2012 05:03:34 -0400
| Newsgroups | gmane.comp.web.pyblosxom.devel |
|---|---|
| Message-ID | <[email protected]> |
--AqsLC8rIMeq19msA Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Attached is a patch that enables pagination in static-rendering mode, pagination being the rendering of index pages which are longer than num_entries by writing them out to multiple pages, combined with the production of navigation strings which the user can include in the templates for those pages. Since: -- doing this as a plugin seemed somewhere between painful and impossible, and -- I think this really should be core functionality anyway, I went ahead and implemented the whole thing in the core. It should work for dynamic rendering, too (or whatever one calls the opposite of static rendering), but I haven't tested that mode. It is meant to supersede the present "paginate" plugin, but the latter should still work (again, untested). It uses all the same config variables, except for "paginate_count_from", which I thought was far too much in the bikeshedding direction to be worth saving. The variable "paginate_linkstyle" accepts, besides the old settings (0 or 1), the more descriptive settings "1 of 4" (same as style 1) or "1234" (same as style 0). For static rendering, instead of the page number being sent in the HTML query, as in http://example.com/blog/index.html?page=2 it has to be part of the filename, as in http://example.com/blog/index_page2.html which is now this change does it. I haven't yet fixed up the documentation to reflect the changes. (As for why I think this should be core functionality, I can't imagine anyone not wanting it, at least for normal weblog use.) -- Norman Yarvin http://yarchive.net/blog --AqsLC8rIMeq19msA Content-Type: text/plain; charset=utf-8 Content-Disposition: attachment; filename="static_pagination.patch" Content-Transfer-Encoding: quoted-printable =46rom 0f284d9b991c40f553da83315fcfd67114c2a931 Mon Sep 17 00:00:00 2001 =46rom: Norman Yarvin <[email protected]> Date: Thu, 15 Mar 2012 16:53:45 -0400 Subject: [PATCH] Allow for pagination of index URLs in static mode, via folding the pagination plugin into the main code --- Pyblosxom/pyblosxom.py | 126 ++++++++++++++++++++++++++++++++++++++++++++= ++- Pyblosxom/tools.py | 56 +++++++++++++++------ 2 files changed, 163 insertions(+), 19 deletions(-) diff --git a/Pyblosxom/pyblosxom.py b/Pyblosxom/pyblosxom.py index 3a1888f..e869d58 100644 --- a/Pyblosxom/pyblosxom.py +++ b/Pyblosxom/pyblosxom.py @@ -1062,6 +1062,14 @@ def blosxom_file_list_handler(args): donefunc=3Dlambda x: x !=3D None, defaultfunc=3Dblosxom_sort_list_handler) =20 + # if we are to be chopping up the list and rendering only a part of it, + # report how many other parts there are to be rendered: + num_entries =3D config.get("num_entries",5) + truncate =3D data.get("truncate",0) + if num_entries > 0 and truncate: + max_page =3D (len(entrylist) - 1) / num_entries + 1 + data["MAX_PAGE"] =3D max_page + args =3D {"request": request, "entry_list": entrylist} =20 entrylist =3D tools.run_callback("truncatelist", args, @@ -1092,7 +1100,11 @@ def blosxom_sort_list_handler(args): def blosxom_truncate_list_handler(args): """If ``config["num_entries"]`` is not 0 and ``data["truncate"]`` is not 0, then this truncates ``args["entry_list"]`` by - ``config["num_entries"]``. + ``config["num_entries"]``. Or if ``data["CURRENT_PAGE"]`` is set + (in static-rendering mode), or if there is a "page=3D" query (in + dynamic mode) rather than just truncating (rendering the first + page), it renders the N'th page. If there is more than one + subpage, it also fills the page navigation string. =20 :param args: args dict with ``request`` object and ``entry_list`` list of entries @@ -1105,12 +1117,120 @@ def blosxom_truncate_list_handler(args): data =3D request.data config =3D request.config =20 + static =3D data.get("STATIC",0) =3D=3D 1 + num_entries =3D config.get("num_entries", 5) truncate =3D data.get("truncate", 0) - if num_entries and truncate: - entrylist =3D entrylist[:num_entries] + max_page =3D (len(entrylist) - 1) / num_entries + 1 + + if num_entries and truncate and max_page > 1: + if static: + page =3D data.get("CURRENT_PAGE",1) + else: + form =3D request.get_form() + page =3D 1 + if form: + try: + page =3D int(form.getvalue("page")) + except: + page =3D 1 + + begin =3D (page - 1) * num_entries + end =3D page * num_entries + entrylist =3D entrylist[begin:end] + make_page_navigation_string(request,page,max_page) + else: + data["page_navigation"] =3D "" + return entrylist =20 +def make_page_navigation_string(request,page,max_page): + """Make HTML code for navigating among the parts of an index page + which has been broken up due to excessive length. The output + is stashed in ``data["page_navigation"]``. + + :param request: the ``request`` object + :param page: the page being rendered + :param max_page: the number of pages this index page is sliced into + """ + + http =3D request.http + data =3D request.data + config =3D request.config + + static =3D data.get("STATIC",0) =3D=3D 1 + + previous_text =3D config.get("paginate_previous_text", "<<") + next_text =3D config.get("paginate_next_text", ">>") + linkstyle =3D config.get("paginate_linkstyle", 1) + + if linkstyle =3D=3D 0 or linkstyle =3D=3D "1234": + linkstyle =3D "1234" + elif linkstyle =3D=3D 1 or linkstyle =3D=3D "1 of 4": + linkstyle =3D "1 of 4" + else: + linkstyle =3D "" + + # + # first task: get the url strings to use in referring to other slices + # of this index pages + # + + url =3D http.get("REQUEST_URI", http.get("HTTP_REQUEST_URI", "")) + + pos =3D url.find("?") + if pos !=3D -1: + query =3D url[pos + 1:] + url =3D url[:pos] + else: + query =3D "" + + if static: + pos =3D url.rfind(".") + baseurl =3D url[1:pos] + extension =3D url[pos:] + url =3D baseurl + extension + url_n =3D baseurl + "_page%d" + extension + else: + query =3D query.split("&") + query =3D [m for m in query if not m.startswith("page=3D")] + if len(query) =3D=3D 0: + url_n =3D url + "?" + "page=3D%d" + else: + url_n =3D url + "?" + "&".join(query) + "&page=3D%d" + + # + # produce the actual navigation string: + # + + output =3D [] + + if page !=3D 1: + if page =3D=3D 2: + previous_url =3D url + else: + previous_url =3D url_n % (page-1) + output.append('<a href=3D"%s">%s</a> ' % (previous_url, previ= ous_text)) + + if linkstyle =3D=3D "1234": + for i in range(1,max_page+1): + if i =3D=3D page: + output.append('[%d]' % i) + else: + if i =3D=3D 1: + url_i =3D url + else: + url_i =3D url_n % i + output.append('<a href=3D"%s">%d</a>' % (url_i, i)) + elif linkstyle =3D=3D "1 of 4": + output.append(' Page %s of %s ' % (page, max_page)) + + if page < max_page: + next_url =3D url_n % (page+1) + output.append(' <a href=3D"%s">%s</a>' % (next_url, next_text= )) + + data["page_navigation"] =3D " ".join(output) + def blosxom_process_path_info(args): """Process HTTP ``PATH_INFO`` for URI according to path specifications, fill in data dict accordingly. diff --git a/Pyblosxom/tools.py b/Pyblosxom/tools.py index 394df8c..17c362b 100644 --- a/Pyblosxom/tools.py +++ b/Pyblosxom/tools.py @@ -942,8 +942,15 @@ def update_static_entry(cdict, entry_filename): render_url_statically(cdict, mem[0], mem[1]) =20 def render_url_statically(cdict, url, querystring): - """Renders a url and saves the rendered output to the - filesystem. + """Renders a url and saves the rendered output to the filesystem. + If an index page is too long (as determined in rendering, and + ultimately by the config parameter num_entries) it breaks it into + multiple pages and renders all the pages, saving the pages past + the first into files whose names are derived from the URL, but + with "_pageN" inserted. Only ".html" files (or files of whichever + extensions are named in the configuration parameter + "paged_extensions") are broken into multiple pages; the rest are + just truncated. =20 :param cdict: config dict :param url: url to render @@ -956,22 +963,34 @@ def render_url_statically(cdict, url, querystring): if not staticdir: raise Exception("You must set static_dir in your config file.") =20 - staticdir =3D cdict.get("static_dir", "") + paged_extensions =3D cdict.get("paged_extensions",[".html"]) =20 - response =3D render_url(cdict, url, querystring) - response.seek(0) + page =3D 1 + while True: + response =3D render_url(cdict, url, querystring, page) + response.seek(0) =20 - fn =3D os.path.normpath(staticdir + os.sep + url) - if not os.path.isdir(os.path.dirname(fn)): - os.makedirs(os.path.dirname(fn)) + fn =3D os.path.normpath(staticdir + os.sep + url) + fn_base, fn_ext =3D os.path.splitext(fn) + if page > 1: + fn =3D fn_base + "_page" + str(page) + fn_ext + + if not os.path.isdir(os.path.dirname(fn)): + os.makedirs(os.path.dirname(fn)) + + f =3D open(fn, "w") + f.write(response.read()) + f.close() + + if fn_ext not in paged_extensions: + break + + page +=3D 1 + if page > response.max_page: + break =20 - # by using the response object the cheesy part of removing the - # HTTP headers from the file is history. - f =3D open(fn, "w") - f.write(response.read()) - f.close() =20 -def render_url(cdict, pathinfo, querystring=3D""): +def render_url(cdict, pathinfo, querystring=3D"", page=3D1): """ Takes a url and a querystring and renders the page that corresponds with that by creating a Request and a Pyblosxom object @@ -981,6 +1000,9 @@ def render_url(cdict, pathinfo, querystring=3D""): :param pathinfo: the ``PATH_INFO`` string; example: ``/dev/pyblosxom/firstpost.html`` :param querystring: the querystring (if any); example: debug=3Dyes + :param page: the page number to render; this is for long index pages + that are to be split into multiple pages; it designates + which of those subpages to render =20 :returns: a Pyblosxom ``Response`` object.=20 """ @@ -999,10 +1021,12 @@ def render_url(cdict, pathinfo, querystring=3D""): "wsgi.errors": sys.stderr, "wsgi.input": None } - data =3D {"STATIC": 1} + data =3D {"STATIC": 1, "CURRENT_PAGE": page } p =3D Pyblosxom(cdict, env, data) p.run(static=3DTrue) - return p.get_response() + response =3D p.get_response() + response.max_page =3D data.get("MAX_PAGE",1) + return response =20 =20 #****************************** --=20 1.7.8.5 --AqsLC8rIMeq19msA Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline ------------------------------------------------------------------------------ This SF email is sponsosred by: Try Windows Azure free for 90 days Click Here http://p.sf.net/sfu/sfd2d-msazure --AqsLC8rIMeq19msA Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Pyblosxom-devel mailing list Pyblosxom-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org https://lists.sourceforge.net/lists/listinfo/pyblosxom-devel --AqsLC8rIMeq19msA--