From a676e11575fd145af0ff9b73a41df93b95fd7d55 Mon Sep 17 00:00:00 2001 From: Jai Sharma Date: Fri, 22 Jan 2010 15:52:44 +0800 Subject: [PATCH] Added the chronological navigation to the post page. While following Nick's post series I felt the need for easy navigation from current post to previous and next post in the series, thus avoiding going back to the index page again and again. Also it is helpful for somebody coming in from a search engine to read the posts in order, or for archive pages. This branch can be safely merged with the delete_handler branch and is kept separate just as a choice to the user. The delete takes care of adjusting the previous and next links automatically. --- generators.py | 53 ++++++++++++++++++++++++++++++++++++++++ models.py | 6 ++++- themes/default/post.html | 6 +++++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/generators.py b/generators.py index cbede42..8db8901 100644 --- a/generators.py +++ b/generators.py @@ -73,6 +73,28 @@ def get_resource_list(cls, post): def get_etag(cls, post): return post.hash + @classmethod + def get_prev_next(cls, post): + """Retrieves the chronologically previous and next post for this post""" + import models + + q = models.BlogPost.all().order('-published') + q.filter('published <', post.published) + prev = q.fetch(1) + + q = models.BlogPost.all().order('published') + q.filter('published >', post.published) + next = q.fetch(1) + if len(prev) > 0: + prev = prev[0] + else: + prev = None + if len(next) > 0: + next = next[0] + else: + next = None + return prev,next + @classmethod def generate_resource(cls, post, resource): import models @@ -83,10 +105,41 @@ def generate_resource(cls, post, resource): template_vals = { 'post': post, } + prev, next = cls.get_prev_next(post) + if prev is not None: + template_vals['prev']=prev + if next is not None: + template_vals['next']=next rendered = utils.render_template("post.html", template_vals) static.set(post.path, rendered, config.html_mime_type) generator_list.append(PostContentGenerator) +class PostPrevNextContentGenerator(PostContentGenerator): + """ContentGenerator for the blog posts chronologically before and after the blog post.""" + + @classmethod + def get_resource_list(cls, post): + prev, next = cls.get_prev_next(post) + resource_list = [res.key().id() for res in (prev,next) if res is not None] + return resource_list + + @classmethod + def generate_resource(cls, post, resource): + import models + post = models.BlogPost.get_by_id(resource) + if post is None: + return + template_vals = { + 'post': post, + } + prev, next = cls.get_prev_next(post) + if prev is not None: + template_vals['prev']=prev + if next is not None: + template_vals['next']=next + rendered = utils.render_template("post.html", template_vals) + static.set(post.path, rendered, config.html_mime_type) +generator_list.append(PostPrevNextContentGenerator) class ListingContentGenerator(ContentGenerator): path = None diff --git a/models.py b/models.py index cc39863..e7a4d88 100644 --- a/models.py +++ b/models.py @@ -58,6 +58,7 @@ def summary_hash(self): return hashlib.sha1(str(val)).hexdigest() def publish(self): + regenerate = False if not self.path: num = 0 content = None @@ -67,9 +68,12 @@ def publish(self): num += 1 self.path = path self.put() + # Force regenerate on new publish. Also helps with generation of + # chronologically previous and next page. + regenerate = True if not self.deps: self.deps = {} - for generator_class, deps in self.get_deps(): + for generator_class, deps in self.get_deps(regenerate=regenerate): for dep in deps: if generator_class.can_defer: deferred.defer(generator_class.generate_resource, None, dep) diff --git a/themes/default/post.html b/themes/default/post.html index d7258fc..48c3cb0 100644 --- a/themes/default/post.html +++ b/themes/default/post.html @@ -15,6 +15,12 @@

{{post.title|escape}}

{{post.published|date:"d F, Y"}}

+ {% if prev %} + + {% endif %} + {% if next %} + + {% endif %} {% if config.disqus_forum %}

Comments