【问题标题】:Getting and showing latest posts in base.html sidebar在 base.html 侧边栏中获取和显示最新帖子
【发布时间】:2021-06-14 11:34:00
【问题描述】:

我正在尝试在 base.html 的侧边栏中显示 3 个最新帖子。我发现了一个先前的问题 (Wagtail - display the three latest posts only on the homepage) 并尝试关注,但帖子没有显示。

如果有任何关于如何进行的提示,我们将不胜感激。谢谢!

# blog/models.py
from django.db import models

from modelcluster.fields import ParentalKey
from modelcluster.contrib.taggit import ClusterTaggableManager
from taggit.models import TaggedItemBase
from wagtail.core.models import Page
from wagtail.core.fields import StreamField
from wagtail.core import blocks
from wagtail.admin.edit_handlers import FieldPanel, StreamFieldPanel
from wagtail.images.blocks import ImageChooserBlock
from wagtail.snippets.models import register_snippet

richtext_features = [
    'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 
    "ol", "ul", "hr", 
    "link", "document-link", 
    "image", "embed",
    "code", "blockquote",
    "superscript", "subscript", "strikethrough",
]


class BlogListingPage(Page):
    """Listing page lists all the Blog pages."""

    template = "blog/blog_listing_page.html"

    custom_title = models.CharField(
        max_length=255,
        blank=False,
        null=False,
        help_text='Overwrites the default title',
    )

    content_panels = Page.content_panels + [
        FieldPanel("custom_title"),
    ]

    def get_context(self, request, *args, **kwargs):
        """Adding custom stuff to our context."""
        context = super().get_context(request, *args, **kwargs)
        context["posts"] = BlogPage.objects.live().public().order_by('-date')
        context["latest_posts"] = context["posts"][:3]

        if request.GET.get('tag', None):
            tags = request.GET.get('tag')
            all_posts = context["posts"].filter(tags__slug__in=[tags])

        return context

    class Meta:

        verbose_name = "Blog Listing Page"
        verbose_name_plural = "Blog Listing Pages"


@register_snippet
class BlogTag(TaggedItemBase):
    content_object = ParentalKey(
        'BlogPage',
        on_delete=models.CASCADE,
    )
    
    class Meta:
        verbose_name = "Blog Tag"
        verbose_name_plural = "Blog Tags"


class BlogPage(Page):
    """ For individual blog pages."""
        
    template = "blog/blog_page.html"
    parent_page_types = ['blog.BlogListingPage']
    tags = ClusterTaggableManager(through=BlogTag, blank=True)

    author = models.CharField(max_length=255, default="Niq")
    date = models.DateField("Post date")
    content = StreamField([
        ('heading', blocks.CharBlock(form_classname="full title")),
        ('standfirst', blocks.RichTextBlock(features=richtext_features)),
        ('paragraph', blocks.RichTextBlock(features=richtext_features)),
        ('image', ImageChooserBlock()),
    ], block_counts={
        'heading': {'min_num': 1, 'max_num': 1,},
        'standfirst': {'max_num': 1,},
    })

    content_panels = Page.content_panels + [
        FieldPanel('author'),
        FieldPanel('date'),
        FieldPanel("tags"),
        StreamFieldPanel('content'),
    ]

    @property
    def heading(self):
        for block in self.content:
            if block.block_type == 'heading':
                return block.value

    @property
    def standfirst(self):
        for block in self.content:
            if block.block_type == 'standfirst':
                return block.value


    class Meta:

        verbose_name = "Blog Page"
        verbose_name_plural = "Blog Pages"

blog/templatetags/show_latest_posts.py

from django import template
register = template.Library()

from ..models import BlogPage

@register.inclusion_tag('blog/show_latest_posts.html')
def show_latest_posts():
    latest_posts = BlogPage.objects.live().public().order_by('-date')[:3]
    return {'latest_posts': latest_posts}
    # return latest_posts

模板/博客/show_latest_posts.html

<b>Latest Posts</b>
{% for post in latest_posts %}
  <br><a href="{{ post.url }}" class="text-body text-decoration-none">{{ post.heading }}</a>
{% endfor %}

base.html 的一部分

<div class="right">
    {% load show_latest_posts %}
    {% show_latest_posts %}
</div>

【问题讨论】:

    标签: django wagtail


    【解决方案1】:

    线

    {% for post in page.latest_posts %}
    

    应该是

    {% for post in latest_posts %}
    

    这里,page.latest_posts 将引用当前页面对象上的 latest_posts 方法,但是您没有这样定义它 - 相反,您在 get_context 方法中设置了 context["latest_posts"],这使得结果在模板中作为变量 latest_posts(不是 page.latest_posts)可用。

    请记住,latest_posts 变量仅适用于您在 get_context 方法中定义该变量的页面类型。在这种情况下,您会发现最新的帖子列表显示在 BlogIndexPage 上,但没有显示在 BlogPage 上。您可以在 BlogPage 上的 get_context 方法中重复相同的代码,但更好的方法可能是使用自定义 inclusion template tag 来检索和显示列表 - 这样,代码是完全独立的,不需要页面模型中的任何额外查询。

    【讨论】:

    • 感谢您的建议。我阅读了文档并尝试了@register.inclusion_tag('base.html'),但无法使其正常工作。你能帮忙看看我上面发布的新models.py吗?注释掉的行是我尝试过但失败的一些内容。
    • @register.inclusion_tag 行需要成为应用程序的 templatetags 文件夹下的专用模块的一部分 - 如果您要走这条路,我建议您阅读 custom template tags 中的文档满的。此外,您不希望为此使用 base.html - 它是一个由仅 博客文章列表组成的模板。
    • 感谢您的帮助!我让它工作并用代码更新了帖子,以防有人发现它有用。我还有另一个问题,也许您可​​以帮助我理解或指向文档。如果我使用return latest_posts 而不是在def show_latest_posts(): 中返回字典-return {'latest_posts': latest_posts},则会收到错误“PageQuerySet”对象不支持项目分配。但是为什么在 models.py 中只使用 return context 就可以了?
    • 因为context 是一本字典。在这两种情况下,您都将返回将在模板上可用的变量字典。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-15
    • 1970-01-01
    相关资源
    最近更新 更多