Switch to date-based URLs everywhere except the feed URLs of old posts, so I don't spam everyone's feedreader.
authorAdam Gomaa <code@adam.gomaa.us>
Sun Feb 01 01:35:02 2009 -0500
changeset 4165a586a8c2f8f
parent 415 5e48e2725b18
child 417 41bb13fc4f7d
Switch to date-based URLs everywhere except the feed URLs of old posts, so I don't spam everyone's feedreader.
agdj/blog/feeds.py
agdj/blog/models.py
agdj/blog/urls.py
agdj/blog/views.py
agdj/core/templates/blog/post_list.html
agdj/core/templates/blog/render_post_summary.html
agdj/core/templates/blog/single_post.html
agdj/utils.py
     1.1 --- a/agdj/blog/feeds.py	Sun Feb 01 01:10:45 2009 -0500
     1.2 +++ b/agdj/blog/feeds.py	Sun Feb 01 01:35:02 2009 -0500
     1.3 @@ -12,7 +12,6 @@
     1.4  
     1.5  """
     1.6  
     1.7 -from django.core.urlresolvers import reverse
     1.8  from django.http import HttpResponse, HttpResponseRedirect, Http404
     1.9  from django.views.decorators.cache import cache_page
    1.10  
    1.11 @@ -24,7 +23,7 @@
    1.12  
    1.13      entry_kwargs = {}
    1.14      entry_kwargs['title'] = entry.title
    1.15 -    entry_kwargs['guid'] = guid = reverse("view-blog-post", args=[entry.slug])
    1.16 +    entry_kwargs['guid'] = guid = entry.urls.feed_url
    1.17      entry_kwargs['link'] = "http://adam.gomaa.us%s" % guid
    1.18      entry_kwargs['description'] = entry.rendered
    1.19      entry_kwargs['pubDate'] = entry.pub_date
    1.20 @@ -37,7 +36,7 @@
    1.21  
    1.22      item_kwargs = {}
    1.23      item_kwargs['title'] = "Comment on %s" % comment.entry.title
    1.24 -    abs_url = reverse("view-blog-post", args=[comment.entry.slug])
    1.25 +    abs_url = comment.entry.feed_url
    1.26      item_kwargs['link'] = "http://adam.gomaa.us%s" % abs_url
    1.27      item_kwargs['guid'] = comment.entry.slug+str(comment.id)
    1.28      item_kwargs['description'] = comment.rendered
     2.1 --- a/agdj/blog/models.py	Sun Feb 01 01:10:45 2009 -0500
     2.2 +++ b/agdj/blog/models.py	Sun Feb 01 01:35:02 2009 -0500
     2.3 @@ -4,7 +4,7 @@
     2.4  from tagging.fields import TagField
     2.5  
     2.6  from agdj.blog.managers import PublicManager
     2.7 -from agdj.utils import cached_property
     2.8 +from agdj.utils import cached_property, dictproperty
     2.9  
    2.10  
    2.11  class Entry(models.Model):
    2.12 @@ -17,6 +17,17 @@
    2.13      pub_date = models.DateTimeField(auto_now_add=True)
    2.14      slug = models.CharField(max_length=64, unique=True)
    2.15      public = models.BooleanField()
    2.16 +    SLUG_ONLY = "slug-only"
    2.17 +    DATE_BASED = "date-based"
    2.18 +    URL_SCHEME_CHOICES = (
    2.19 +        (SLUG_ONLY, "Slug Only"),
    2.20 +        (DATE_BASED, "Date-based"),
    2.21 +        )
    2.22 +    feed_url_scheme = models.CharField(
    2.23 +        max_length=64, choices=URL_SCHEME_CHOICES,
    2.24 +        help_text="Does this post use the new date-based URL or the old "
    2.25 +        "slug-based one in feed URLs and GUIDs?",
    2.26 +        default=DATE_BASED)
    2.27  
    2.28      # This is a hack that even I don't understand
    2.29      text_tags = TagField(db_column="tags")
    2.30 @@ -45,6 +56,23 @@
    2.31  
    2.32          return super(Entry, self).save(*args, **kwargs)
    2.33  
    2.34 +    @dictproperty
    2.35 +    def urls(self, name):
    2.36 +        from django.core.urlresolvers import reverse
    2.37 +
    2.38 +        if name == "feed_url":
    2.39 +            if self.feed_url_scheme == self.DATE_BASED:
    2.40 +                return self.urls.view
    2.41 +            else:
    2.42 +                return reverse("redirect-to-date-url", args=[self.slug])
    2.43 +        elif name == "view":
    2.44 +                return reverse("view-blog-post",
    2.45 +                               args=[self.pub_date.year,
    2.46 +                                     self.pub_date.strftime("%b").lower(),
    2.47 +                                     self.pub_date.day,
    2.48 +                                     self.slug])
    2.49 +
    2.50 +
    2.51  
    2.52      @cached_property
    2.53      def rendered(self):
     3.1 --- a/agdj/blog/urls.py	Sun Feb 01 01:10:45 2009 -0500
     3.2 +++ b/agdj/blog/urls.py	Sun Feb 01 01:35:02 2009 -0500
     3.3 @@ -11,7 +11,10 @@
     3.4      (r'^feed/$', feeds.latest),
     3.5      (r'^feed/comments/$', feeds.comments),
     3.6      (r'^feed/latest/$', redirect_to, {"url":"/blog/feed/"}),
     3.7 -    url(r'^(?P<slug>[-\w]+)/$', views.single_post, {}, "view-blog-post"),
     3.8 +    url(r'^(?P<slug>[-\w]+)/$', views.redirect_to_date_version, {}, "redirect-to-date-url"),
     3.9 +    url(r'^(?P<year>\d{4})/(?P<month>\w+)/(?P<day>\d+)/(?P<slug>[-\w]+)/$',
    3.10 +        views.single_post, {},
    3.11 +        "view-blog-post"),
    3.12  )
    3.13  
    3.14  
     4.1 --- a/agdj/blog/views.py	Sun Feb 01 01:10:45 2009 -0500
     4.2 +++ b/agdj/blog/views.py	Sun Feb 01 01:35:02 2009 -0500
     4.3 @@ -8,8 +8,14 @@
     4.4  from agdj.utils import use_template
     4.5  
     4.6  
     4.7 +def redirect_to_date_version(request, slug):
     4.8 +    "Redirect requests from the old URL scheme to the new one"
     4.9 +    post = get_object_or_404(models.Entry, slug=slug)
    4.10 +    return HttpResponseRedirect(post.urls.view)
    4.11 +
    4.12 +
    4.13  @use_template("blog/single_post.html")
    4.14 -def single_post(request, slug):
    4.15 +def single_post(request, year, month, day, slug):
    4.16      "Show a single post"
    4.17  
    4.18      post = get_object_or_404(models.Entry, slug=slug)
     5.1 --- a/agdj/core/templates/blog/post_list.html	Sun Feb 01 01:10:45 2009 -0500
     5.2 +++ b/agdj/core/templates/blog/post_list.html	Sun Feb 01 01:35:02 2009 -0500
     5.3 @@ -2,10 +2,8 @@
     5.4  {% load cache %}
     5.5  
     5.6  {% block content %}
     5.7 -{% cache 500 all_posts %}
     5.8  {% for object in posts %}
     5.9  {% include "blog/render_post_summary.html" %}
    5.10  {% endfor %}
    5.11 -{% endcache %}
    5.12  {% endblock %}
    5.13  
     6.1 --- a/agdj/core/templates/blog/render_post_summary.html	Sun Feb 01 01:10:45 2009 -0500
     6.2 +++ b/agdj/core/templates/blog/render_post_summary.html	Sun Feb 01 01:35:02 2009 -0500
     6.3 @@ -1,8 +1,7 @@
     6.4  {% load cache humanize microformats mkdn2 %}
     6.5  
     6.6 -{% cache 500 post_summary object.slug %}
     6.7  <div class="post-summary">
     6.8 -  <h3><a href="{% url agdj.blog.views.single_post object.slug %}">{{ object.title }}</a></h3>
     6.9 +  <h3><a href="{{ object.urls.view }}">{{ object.title }}</a></h3>
    6.10  {% with object.public_comments as comments %}
    6.11    <p>Posted <span class="humanize iso8601">{{ object.pub_date|iso8601 }}</span> - {% if comments %}
    6.12  {{ comments|length|apnumber|capfirst }} comment{{ comments|pluralize }}
    6.13 @@ -15,4 +14,3 @@
    6.14  </div>
    6.15  <div class="description">{{ object.description|markdown2 }}</div>
    6.16  </div>
    6.17 -{% endcache %}
     7.1 --- a/agdj/core/templates/blog/single_post.html	Sun Feb 01 01:10:45 2009 -0500
     7.2 +++ b/agdj/core/templates/blog/single_post.html	Sun Feb 01 01:35:02 2009 -0500
     7.3 @@ -7,7 +7,7 @@
     7.4  {% block header %}
     7.5    <h1>
     7.6      <a href="{% url agdj.blog.views.post_list %}">blog:</a>
     7.7 -    <a href="{% url agdj.blog.views.single_post post.slug %}">{{ post.title }}</a></h1>
     7.8 +    <a href="{{ post.urls.view }}">{{ post.title }}</a></h1>
     7.9  {% endblock %}
    7.10  
    7.11  {% block metadata %}
     8.1 --- a/agdj/utils.py	Sun Feb 01 01:10:45 2009 -0500
     8.2 +++ b/agdj/utils.py	Sun Feb 01 01:35:02 2009 -0500
     8.3 @@ -56,3 +56,17 @@
     8.4  
     8.5          return val
     8.6      return property(_closure)
     8.7 +
     8.8 +
     8.9 +def dictproperty(method):
    8.10 +    """Turn dictionary or attribute access into a function call"""
    8.11 +
    8.12 +    class _Object(object):
    8.13 +        def __init__(self, obj):
    8.14 +            self.obj = obj
    8.15 +        def __getattr__(self, attr):
    8.16 +            return method(self.obj, attr)
    8.17 +        __getitem__ = __getattr__
    8.18 +    _Object.__name__ = method.__name__
    8.19 +
    8.20 +    return property(_Object)