Skip to content

Commit

Permalink
Merge pull request #115 from springload/fix/blog-landing
Browse files Browse the repository at this point in the history
Make blog landing page a routable page which also serves it's children
  • Loading branch information
haydngreatnews authored Jun 24, 2024
2 parents 562d710 + c867698 commit 26bdb47
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 65 deletions.
87 changes: 73 additions & 14 deletions cdhweb/blog/models.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from datetime import date

from django.core.paginator import Paginator
from django.db import models
from django.db.models.fields.related import RelatedField
from django.shortcuts import get_object_or_404
from django.urls import reverse
from django.utils.dateformat import format
from django.utils.functional import cached_property
Expand All @@ -12,6 +14,7 @@
from modelcluster.models import ClusterableModel
from taggit.models import TaggedItemBase
from wagtail.admin.panels import FieldPanel, FieldRowPanel, InlinePanel, MultiFieldPanel
from wagtail.contrib.routable_page.models import RoutablePageMixin, path, re_path
from wagtail.fields import RichTextField
from wagtail.models import Orderable, Page, PageManager, PageQuerySet
from wagtail.search import index
Expand Down Expand Up @@ -186,6 +189,25 @@ def author_list(self):
"""Comma-separated list of author names."""
return ", ".join(str(author.person) for author in self.authors.all())

def get_url_parts(self, *args, **kwargs):
"""Custom blog post URLs of the form /updates/2014/03/01/my-post."""
url_parts = super().get_url_parts(*args, **kwargs)
# NOTE evidently these can sometimes be None; unclear why – perhaps it
# gets called in a context where the request is unavailable. Seems to
# happen immediately on page creation; the creation still succeeds.
if url_parts and self.first_published_at:
site_id, root_url, _ = url_parts
page_path = self.get_parent().specific.reverse_subpage(
"dated_child",
kwargs={
"year": self.first_published_at.year,
# force two-digit month and day
"month": "%02d" % self.first_published_at.month,
"day": "%02d" % self.first_published_at.day,
"slug": self.slug,
},
)
return site_id, root_url, page_path

def get_sitemap_urls(self, request):
"""Override sitemap listings to add priority for featured posts."""
Expand All @@ -208,9 +230,12 @@ class BlogLinkPageArchived(LinkPage):
subpage_types = [BlogPost]


class BlogLandingPage(StandardHeroMixinNoImage, Page):
class BlogLandingPage(StandardHeroMixinNoImage, RoutablePageMixin, Page):
"""Container page that defines where Event pages can be created."""

page_size = 15
template_name = "blog/blog_landing_page.html"

content_panels = StandardHeroMixinNoImage.content_panels

search_fields = StandardHeroMixinNoImage.search_fields
Expand All @@ -219,26 +244,60 @@ class BlogLandingPage(StandardHeroMixinNoImage, Page):

subpage_types = [BlogPost, ContentPage]

def get_posts_for_year_and_month(self, month, year):
# get blogs by year and month
return (
self.get_children()
.live()
.filter(first_published_at__year=year, first_published_at__month=month)
.order_by("-first_published_at")
def get_context(self, request, year=None, month=None):
context = super().get_context(request)

if year:
posts = self.get_posts_for_year_and_month(year=year, month=month)
else:
posts = self.get_latest_posts()

page_number = request.GET.get("page") or 1
paginator = Paginator(posts, self.page_size)
page = paginator.page(page_number)
context.update(
{
"paginator": paginator,
"is_paginated": page.has_other_pages(),
"page_obj": page, # Used in pagination template
"posts": page, # Used in page template
}
)

def get_posts_for_year(self, year):
# get blogs by year
return (
context["date_list"] = self.get_list_of_dates()

return context

@path("<int:year>/", name="by-year")
@path("<int:year>/<int:month>/", name="by-month")
def by_date(self, request, year=None, month=None):
context = self.get_context(request, year=year, month=month)
return self.render(request, context_overrides=context)

@path("<int:year>/<int:month>/<int:day>/<slug:slug>/", name="dated_child")
def dated_child(self, request, year=None, month=None, day=None, slug=None):
child = get_object_or_404(
self.get_children()
.live()
.filter(first_published_at__year=year)
.order_by("-first_published_at")
.public()
.filter(
first_published_at__year=year,
first_published_at__month=month,
first_published_at__day=day,
),
slug=slug,
)
return child.specific.serve(request)

def get_posts_for_year_and_month(self, year=None, month=None):
# get blogs by year and month
child_qs = self.get_latest_posts().filter(first_published_at__year=year)
if month:
child_qs = child_qs.filter(first_published_at__month=month)
return child_qs

def get_latest_posts(self):
child_pages = self.get_children().live()
child_pages = self.get_children().live().public().specific()

# Fetch all posts ordered by most recently published
return child_pages.order_by("-first_published_at")
Expand Down
11 changes: 0 additions & 11 deletions cdhweb/blog/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,6 @@

app_name = "blog"
urlpatterns = [
re_path(r"^(?P<slug>[\w-]+)/$", views.BlogLandingPageView.as_view(), name="list"),
re_path(
r"^(?P<slug>[\w-]+)/(?P<year>\d{4})/$",
views.BlogLandingPageView.as_view(),
name="by-year",
),
re_path(
r"^(?P<slug>[\w-]+)/(?P<year>\d{4})/(?P<month>\d{2})/$",
views.BlogLandingPageView.as_view(),
name="by-month",
),
path("rss/", views.RssBlogPostFeed(), name="rss"),
path("atom/", views.AtomBlogPostFeed(), name="atom"),
]
41 changes: 2 additions & 39 deletions cdhweb/blog/views.py
Original file line number Diff line number Diff line change
@@ -1,44 +1,7 @@
from django.contrib.syndication.views import Feed
from django.utils.feedgenerator import Atom1Feed
from django.views.generic import ListView
from django.views.generic.detail import DetailView

from cdhweb.blog.models import BlogLandingPage, BlogPost
from cdhweb.pages.views import LastModifiedMixin


class BlogLandingPageView(ListView):
model = BlogLandingPage
template_name = "blog/blog_landing_page.html"
context_object_name = "posts"
paginate_by = 15
make_object_list = True

def get_object(self):
slug = self.kwargs.get("slug")
return BlogLandingPage.objects.get(slug=slug)

def get_queryset(self, **kwargs):
month = self.kwargs.get("month")
year = self.kwargs.get("year")

if month and year:
posts = self.get_object().get_posts_for_year_and_month(
int(month), int(year)
)
elif year:
posts = self.get_object().get_posts_for_year(int(year))
else:
# if month and year are not supplied then supply all posts from newest to oldest
posts = self.get_object().get_latest_posts()

return posts

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["date_list"] = self.get_object().get_list_of_dates()
context["self"] = self.get_object()
return context

from cdhweb.blog.models import BlogPost


class RssBlogPostFeed(Feed):
Expand Down
2 changes: 1 addition & 1 deletion cdhweb/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
path("_500/", lambda _: 1 / 0), # for testing 500 error page
# main apps
path("people/", include("cdhweb.people.urls", namespace="people")),
path("", include("cdhweb.blog.urls", namespace="blog")),
path("blog/", include("cdhweb.blog.urls", namespace="blog")),
path("events/", include("cdhweb.events.urls", namespace="event")),
path("projects/", include("cdhweb.projects.urls", namespace="projects")),
# search
Expand Down

0 comments on commit 26bdb47

Please sign in to comment.