From 0c573e77f3f58a6494ea58f5263b7b2b4f6070b9 Mon Sep 17 00:00:00 2001 From: tata Date: Mon, 28 Aug 2023 00:54:20 +0200 Subject: [PATCH] For #46 :sparkles: add categs links on post detail page as menu for search --- src/posts/context_processors.py | 2 -- src/posts/mixins.py | 27 +++++++++++++++++ src/posts/models/categ_model.py | 21 +++++++++++++ src/posts/templatetags/tree_cats.py | 2 +- src/posts/tests/test_web.py | 36 ++++++++++++++++++++++- src/posts/views.py | 12 ++++++-- src/templates/components/post_categs.html | 12 ++++++++ src/templates/posts/post_detail.html | 5 +++- 8 files changed, 109 insertions(+), 8 deletions(-) create mode 100644 src/posts/mixins.py create mode 100644 src/templates/components/post_categs.html diff --git a/src/posts/context_processors.py b/src/posts/context_processors.py index 83c682d..089d491 100644 --- a/src/posts/context_processors.py +++ b/src/posts/context_processors.py @@ -15,7 +15,6 @@ def build_crumbs(request): crumbs.append({"name": "posts", "url": reverse("posts:post_list")}) if match.url_name == "post_detail": post = get_object_or_404(Post, slug=match.kwargs["slug"]) - print(post) crumbs.append( { "name": post.title, @@ -25,5 +24,4 @@ def build_crumbs(request): ), } ) - print("crumbs are ", crumbs) return {"crumbs": crumbs} diff --git a/src/posts/mixins.py b/src/posts/mixins.py new file mode 100644 index 0000000..6d2050f --- /dev/null +++ b/src/posts/mixins.py @@ -0,0 +1,27 @@ +from django.urls import reverse + + +class CategoryCrumbMixin: + def get_post_categs_path(self) -> list: + """ + list of dict's based on a given p.category: + {key:p.category slug, value: p.category name} + incl ancestors for UI: categs links + """ + post = self.get_object() + cats_names = post.categ.get_name_slug_chain() + slugs_keys = cats_names["path_slug"].split("/") + names_vals = cats_names["path_name"].split("/") + if len(slugs_keys) == len(names_vals): + res = dict(zip(slugs_keys, names_vals, strict=True)) + else: + return [] + chain_crumbs = [] + for slug, name in res.items(): + chain_crumbs.append( + { + "path": reverse("posts:cat_search", kwargs={"slug": slug}), + "name": name, + } + ) + return chain_crumbs diff --git a/src/posts/models/categ_model.py b/src/posts/models/categ_model.py index 11f6ded..ff4b0da 100644 --- a/src/posts/models/categ_model.py +++ b/src/posts/models/categ_model.py @@ -49,5 +49,26 @@ def get_full_path(self): path_slug += f"/{self.slug}" return path_slug + def get_name_slug_chain(self) -> dict: + """ + create dict of name(s)/slug(s) of a given category + incl ancestors + """ + if self.is_root(): + path_name = self.name + path_slug = self.slug + + else: + path_name = "/".join( + list(self.get_ancestors().values_list("name", flat=True)) + ) + path_name += f"/{self.name}" + path_slug = "/".join( + list(self.get_ancestors().values_list("slug", flat=True)) + ) + path_slug += f"/{self.slug}" + + return {"path_name": path_name, "path_slug": path_slug} + def __str__(self): return f"Category: {self.name}" diff --git a/src/posts/templatetags/tree_cats.py b/src/posts/templatetags/tree_cats.py index d6e6be8..10b484a 100644 --- a/src/posts/templatetags/tree_cats.py +++ b/src/posts/templatetags/tree_cats.py @@ -60,7 +60,7 @@ def recursetree(parser, token): return RecrTreeNode(nodelist, queryset_var) -@register.inclusion_tag("components/categ_menu.html") +@register.inclusion_tag("components/categ_bar.html") def show_categs(**kwargs): categs = Category.get_root_nodes() return {"categs": categs, **kwargs} diff --git a/src/posts/tests/test_web.py b/src/posts/tests/test_web.py index b35034f..23cab64 100644 --- a/src/posts/tests/test_web.py +++ b/src/posts/tests/test_web.py @@ -11,7 +11,7 @@ from src.contacts.tests.factories import NewsLetterFactory from src.core.utils.admin_help import admin_change_url from src.posts.models.post_model import Post -from src.posts.tests.factories import PostFactory +from src.posts.tests.factories import CategoryFactory, PostFactory User = get_user_model() TestApp.__test__ = False @@ -101,3 +101,37 @@ def test_tag_seacrh(self): self.assertEqual(resp2.status_code, 200) self.assertEqual(posts.count(), 1) + + +@override_settings(LANGUAGE_CODE="ru", LANGUAGES=(("ru", "Russian"),)) +class CategMenuTestCase(WebTest): + def setUp(self) -> None: + self.categ_root = CategoryFactory(name="grand_pa") + self.categ_pa = self.categ_root.add_child(name="pa") + self.categ_kid = self.categ_pa.add_child(name="kid") + self.post = PostFactory( + categ=self.categ_kid, status=Post.CurrentStatus.PUB.value + ) + + def test_post_detail_categs_menu(self): + """display post detail page with corresp categs as links""" + chain_ = self.post.categ.get_name_slug_chain() + expected_chain = { + "path_name": "grand_pa/pa/kid", + "path_slug": "grand_pa/pa/kid", + } + + start_url = reverse("posts:post_detail", kwargs={"slug": self.post.slug}) + + resp = self.app.get(start_url) + + post_categ_menu = resp.html.find("ol", id="post_categ") + a_links = resp.html.find_all("a", class_="post_categ__link") + href = a_links[0].attrs["href"] + lang = href.split("/")[1] + + self.assertEqual(self.categ_root.get_descendants().count(), 2) + self.assertEqual(chain_, expected_chain) + self.assertIsNotNone(post_categ_menu) + self.assertTrue(len(a_links), 3) + self.assertTrue(lang, "ru") diff --git a/src/posts/views.py b/src/posts/views.py index 85e1d6b..9b15556 100644 --- a/src/posts/views.py +++ b/src/posts/views.py @@ -10,6 +10,8 @@ from src.posts.models.categ_model import Category from src.posts.models.post_model import Post +from .mixins import CategoryCrumbMixin + class PostList(ListView): @@ -21,7 +23,7 @@ class PostList(ListView): paginate_by = 2 def get_queryset(self): - print("looking for posts") + # print("looking for posts") return ( Post.objects.get_public() .select_related("categ", "author") @@ -29,10 +31,15 @@ def get_queryset(self): ) -class PostDetail(DetailView): +class PostDetail(CategoryCrumbMixin, DetailView): model = Post template_name = "posts/post_detail.html" + def get_context_data(self, **kwargs): + ctx = super().get_context_data(**kwargs) + ctx["cats_path"] = self.get_post_categs_path() + return ctx + class PostTagSearch(ListView): template_name = "posts/post_list.html" @@ -70,7 +77,6 @@ class SearchPost(ListView): search in ukrainian: via model manager(no config in this lang) """ - # model = Post template_name = "posts/post_list.html" context_object_name = "posts" paginate_by = 5 diff --git a/src/templates/components/post_categs.html b/src/templates/components/post_categs.html new file mode 100644 index 0000000..357a301 --- /dev/null +++ b/src/templates/components/post_categs.html @@ -0,0 +1,12 @@ +{% load static %} + \ No newline at end of file diff --git a/src/templates/posts/post_detail.html b/src/templates/posts/post_detail.html index 02b3ced..ad1699d 100644 --- a/src/templates/posts/post_detail.html +++ b/src/templates/posts/post_detail.html @@ -15,7 +15,10 @@

{{post.title}}

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

- {%trans "category" %}: {{post.categ.name}} + +
{%trans "category" %}: + {% include "components/post_categs.html" with categ_dict=cats_path %} +
{{post.content|safe}}