Implement category taxonomy and navigation (Issue #35) #36
@@ -49,10 +49,7 @@ class HomePage(Page):
|
|||||||
id__in=ArticlePage.objects.live().public().values_list("tags__id", flat=True)
|
id__in=ArticlePage.objects.live().public().values_list("tags__id", flat=True)
|
||||||
).distinct().order_by("name")
|
).distinct().order_by("name")
|
||||||
)
|
)
|
||||||
category_ids = ArticlePage.objects.live().public().values_list("category_id", flat=True)
|
ctx["available_categories"] = Category.objects.filter(show_in_nav=True).order_by("sort_order", "name")
|
||||||
ctx["available_categories"] = Category.objects.filter(show_in_nav=True, id__in=category_ids).order_by(
|
|
||||||
"sort_order", "name"
|
|
||||||
)
|
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
|
|
||||||
@@ -76,9 +73,7 @@ class ArticleIndexPage(RoutablePageMixin, Page):
|
|||||||
def get_listing_context(self, request, active_category=None):
|
def get_listing_context(self, request, active_category=None):
|
||||||
tag_slug = request.GET.get("tag")
|
tag_slug = request.GET.get("tag")
|
||||||
articles = self.get_articles()
|
articles = self.get_articles()
|
||||||
all_articles = articles
|
available_categories = Category.objects.order_by("sort_order", "name")
|
||||||
category_ids = all_articles.values_list("category_id", flat=True)
|
|
||||||
available_categories = Category.objects.filter(id__in=category_ids).order_by("sort_order", "name")
|
|
||||||
category_links = [
|
category_links = [
|
||||||
{"category": category, "url": self.get_category_url(category)}
|
{"category": category, "url": self.get_category_url(category)}
|
||||||
for category in available_categories
|
for category in available_categories
|
||||||
@@ -111,9 +106,7 @@ class ArticleIndexPage(RoutablePageMixin, Page):
|
|||||||
|
|
||||||
@route(r"^category/(?P<category_slug>[-\w]+)/$")
|
@route(r"^category/(?P<category_slug>[-\w]+)/$")
|
||||||
def category_listing(self, request, category_slug):
|
def category_listing(self, request, category_slug):
|
||||||
category_ids = self.get_articles().values_list("category_id", flat=True)
|
category = get_object_or_404(Category, slug=category_slug)
|
||||||
category_qs = Category.objects.filter(id__in=category_ids)
|
|
||||||
category = get_object_or_404(category_qs, slug=category_slug)
|
|
||||||
return self.render(request, context_overrides=self.get_listing_context(request, active_category=category))
|
return self.render(request, context_overrides=self.get_listing_context(request, active_category=category))
|
||||||
|
|
||||||
def get_context(self, request, *args, **kwargs):
|
def get_context(self, request, *args, **kwargs):
|
||||||
|
|||||||
@@ -233,3 +233,14 @@ def test_article_index_category_route_supports_tag_filter(client, home_page):
|
|||||||
assert resp.status_code == 200
|
assert resp.status_code == 200
|
||||||
assert "Keep Me" in html
|
assert "Keep Me" in html
|
||||||
assert "Drop Me" not in html
|
assert "Drop Me" not in html
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_article_index_category_route_allows_empty_existing_category(client, home_page):
|
||||||
|
index = ArticleIndexPage(title="Articles", slug="articles")
|
||||||
|
home_page.add_child(instance=index)
|
||||||
|
Category.objects.create(name="Opinion", slug="opinion")
|
||||||
|
|
||||||
|
resp = client.get("/articles/category/opinion/")
|
||||||
|
assert resp.status_code == 200
|
||||||
|
assert "No articles found." in resp.content.decode()
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from django import template
|
|||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from wagtail.models import Site
|
from wagtail.models import Site
|
||||||
|
|
||||||
from apps.blog.models import ArticleIndexPage, TagMetadata
|
from apps.blog.models import ArticleIndexPage, Category, TagMetadata
|
||||||
from apps.core.models import SiteSettings
|
from apps.core.models import SiteSettings
|
||||||
from apps.legal.models import LegalPage
|
from apps.legal.models import LegalPage
|
||||||
|
|
||||||
@@ -58,9 +58,7 @@ def get_categories_nav(context):
|
|||||||
index_page = index_qs.first()
|
index_page = index_qs.first()
|
||||||
if not index_page:
|
if not index_page:
|
||||||
return []
|
return []
|
||||||
categories = index_page.get_listing_context(
|
categories = Category.objects.filter(show_in_nav=True).order_by("sort_order", "name")
|
||||||
request, active_category=None
|
|
||||||
)["available_categories"].filter(show_in_nav=True)
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
"name": category.name,
|
"name": category.name,
|
||||||
|
|||||||
@@ -37,3 +37,14 @@ def test_categories_nav_tag_renders_category_link(client, home_page):
|
|||||||
resp = client.get("/")
|
resp = client.get("/")
|
||||||
assert resp.status_code == 200
|
assert resp.status_code == 200
|
||||||
assert "/articles/category/reviews/" in resp.content.decode()
|
assert "/articles/category/reviews/" in resp.content.decode()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_categories_nav_tag_includes_empty_nav_category(client, home_page):
|
||||||
|
index = ArticleIndexPage(title="Articles", slug="articles")
|
||||||
|
home_page.add_child(instance=index)
|
||||||
|
Category.objects.create(name="Benchmarks", slug="benchmarks", show_in_nav=True)
|
||||||
|
|
||||||
|
resp = client.get("/")
|
||||||
|
assert resp.status_code == 200
|
||||||
|
assert "/articles/category/benchmarks/" in resp.content.decode()
|
||||||
|
|||||||
Reference in New Issue
Block a user