diff --git a/docs/templatetags.md b/docs/templatetags.md index 9510e87..a3b9b0f 100644 --- a/docs/templatetags.md +++ b/docs/templatetags.md @@ -452,12 +452,14 @@ Outputs: ## post_title_link -Returns the title of the current post as a link if it's part of a collection, or just the title if it's a -single post. +Returns the title of the current post as a link if it's part of a collection, or just the title if it's single post. + +The `force_link` argument can be used to always return the link, regardless if it's part of a collection or not. ### Arguments - `link_class` (optional): CSS class(es) to apply to the link. +- `force_link` (optional, boolean): Always displays a link when true. *Note* - this is a keyword-only argument. ### Returns @@ -493,6 +495,20 @@ Outputs: My Post Title ``` +Or, to force the link, even when just a single post is displayed: + +```django +{% post_title_link force_link=True %} +``` + +Outputs: + +```html +My Post Title +``` + + + ## post_author Returns the display name of the post's author. diff --git a/pyproject.toml b/pyproject.toml index b9a5129..046fc02 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "djpress" -version = "0.9.4" +version = "0.9.5" description = "A blog application for Django sites, inspired by classic WordPress." readme = "README.md" requires-python = ">=3.10" diff --git a/src/djpress/templatetags/djpress_tags.py b/src/djpress/templatetags/djpress_tags.py index 4c3998c..29d686d 100644 --- a/src/djpress/templatetags/djpress_tags.py +++ b/src/djpress/templatetags/djpress_tags.py @@ -256,6 +256,21 @@ def have_posts(context: Context) -> list[Post | None] | Page: return [] +@register.simple_tag(takes_context=True) +def get_recent_posts(context: Context) -> models.QuerySet[Post]: + """Return the recent posts. + + This returns the most recent published posts, and tries to be efficient by checking if there's a `posts` object we + can use. + """ + posts: Page | None = context.get("posts") + + if isinstance(posts, Page) and posts.number == 1: + return posts.object_list + + return Post.post_objects.get_recent_published_posts() + + @register.simple_tag(takes_context=True) def post_title(context: Context) -> str: """Return the title of a post. @@ -274,19 +289,19 @@ def post_title(context: Context) -> str: @register.simple_tag(takes_context=True) -def post_title_link(context: Context, link_class: str = "") -> str: +def post_title_link(context: Context, link_class: str = "", *, force_link: bool = False) -> str: """Return the title link for a post. - If the post is part of a posts collection, then return the title and a link to the - post. - - If the post is a single post, then return just the title of the post with no link. + If the post is part of a posts collection, then return the title and a link to the post. If the post is a single + post, then return just the title of the post with no link. But this behavior can be overridden by setting + `force_link` to `True`. Otherwise return and empty string. Args: context: The context. link_class: The CSS class(es) for the link. + force_link: Whether to force the link to be displayed. Returns: str: The title link for the post. @@ -294,7 +309,7 @@ def post_title_link(context: Context, link_class: str = "") -> str: post: Post | None = context.get("post") posts: Page | None = context.get("posts") - if posts and post: + if (posts and post) or force_link: link_class_html = f' class="{link_class}"' if link_class else "" output = f'{post.title}' diff --git a/tests/test_templatetags_djpress_tags.py b/tests/test_templatetags_djpress_tags.py index 56315a9..1cb420b 100644 --- a/tests/test_templatetags_djpress_tags.py +++ b/tests/test_templatetags_djpress_tags.py @@ -106,6 +106,22 @@ def test_post_title_link_no_context(): assert djpress_tags.post_title_link(context) == expected_output +@pytest.mark.django_db +def test_post_title_link_single_post(test_post1): + context = Context({"post": test_post1}) + assert djpress_tags.post_title_link(context) == test_post1.title + + +@pytest.mark.django_db +def test_post_title_link_single_post_force_link(test_post1): + context = Context({"post": test_post1}) + + # this generates a URL based on the slug only - this is prefixed with the POST_PREFIX setting + post_url = test_post1.url + expected_output = f'{test_post1.title}' + assert djpress_tags.post_title_link(context, force_link=True) == expected_output + + @pytest.mark.django_db def test_post_title_link_with_prefix(settings, test_post1): # Confirm settings in settings_testing.py @@ -1443,3 +1459,41 @@ def test_rss_url(settings): assert settings.DJPRESS_SETTINGS["RSS_PATH"] == "test-rss" expected_output = "/test-rss/" assert djpress_tags.rss_url() == expected_output + + +@pytest.mark.django_db +def test_get_recent_posts(settings, test_post1, test_post2, test_post3): + assert settings.DJPRESS_SETTINGS["RECENT_PUBLISHED_POSTS_COUNT"] == 3 + posts = Paginator( + Post.post_objects.get_published_posts(), + settings.DJPRESS_SETTINGS["RECENT_PUBLISHED_POSTS_COUNT"], + ) + page = posts.get_page(number=None) + context = Context({"posts": page}) + tag_get_recent_posts = list(djpress_tags.get_recent_posts(context)) + page_posts = list(page.object_list) + assert tag_get_recent_posts == page_posts + + # Test case 2 - 2 pages, i.e. 3 posts with 2 posts per page + settings.DJPRESS_SETTINGS["RECENT_PUBLISHED_POSTS_COUNT"] = 2 + posts = Paginator( + Post.post_objects.get_published_posts(), + settings.DJPRESS_SETTINGS["RECENT_PUBLISHED_POSTS_COUNT"], + ) + page = posts.get_page(number=2) + context = Context({"posts": page}) + tag_get_recent_posts = list(djpress_tags.get_recent_posts(context)) + page_posts = list(page.object_list) + assert tag_get_recent_posts != page_posts + + # Test case 3 - 3 pages, i.e. 3 posts with 1 posts per page + settings.DJPRESS_SETTINGS["RECENT_PUBLISHED_POSTS_COUNT"] = 1 + posts = Paginator( + Post.post_objects.get_published_posts(), + settings.DJPRESS_SETTINGS["RECENT_PUBLISHED_POSTS_COUNT"], + ) + page = posts.get_page(number=3) + context = Context({"posts": page}) + tag_get_recent_posts = list(djpress_tags.get_recent_posts(context)) + page_posts = list(page.object_list) + assert tag_get_recent_posts != page_posts diff --git a/uv.lock b/uv.lock index 39cb68e..07fe660 100644 --- a/uv.lock +++ b/uv.lock @@ -145,7 +145,7 @@ wheels = [ [[package]] name = "djpress" -version = "0.9.4" +version = "0.9.5" source = { editable = "." } dependencies = [ { name = "django" },