Reputation: 91
I am using Wagtail for Django and want to call a grandchildren in the template but don't know how to do that. I am new at this and can't seem to find anything in the wagtail documentation. I see the Page Query Reference docs here but don't know how to apply it.
My Django project tree are as follows:
project/
home/
models.py
> class HomePage
news/
models.py
> class NewsPostPage
> class NewsIndexPage
In the home template, I want to insert the most current news from the news app to the template.
home/models.py
from django.db import models
from django.utils.translation import ugettext_lazy as _
from modelcluster.models import ParentalKey
from wagtail.admin.edit_handlers import FieldPanel
from wagtail.core.models import Page
from news.models import NewsIndexPage
class HomePage(Page):
why_choose_us_title_en = models.CharField(
verbose_name=_('[EN] Why Choose Us Title'),
max_length=200,
default='',
blank=True,
)
why_choose_us_subtitle_en = models.CharField(
verbose_name=_('[EN]Why Choose Us Subtitle'),
max_length=200,
default='',
blank=True,
)
content_panels = Page.content_panels + [
FieldPanel('why_choose_us_title_en', classname='full title'),
FieldPanel('why_choose_us_subtitle_en'),
]
subpage_types = [
'news.NewsIndexPage',
]
@property
def featured_products(self):
return ProductPage.objects.filter(featured=True)
news_index = NewsIndexPage
news/models.py
from datetime import timedelta
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
from wagtail.admin.edit_handlers import FieldPanel, RichTextFieldPanel
from wagtail.core.fields import RichTextField
from wagtail.core.models import Page
from wagtail.images.edit_handlers import ImageChooserPanel
from base.models import TranslatedField
class NewsPostPage(Page):
news_title_en = models.CharField(
max_length=7250,
verbose_name=_('[EN] News Post Page Title'),
blank=True,
default='',
)
news_text_en = RichTextField(
verbose_name=_('[EN] News Text'),
blank=True,
default='',
help_text=_('[EN] News content')
)
preview_text_en = RichTextField(
verbose_name=_('[EN] News Preview Text'),
blank=True,
default='',
help_text=_('[EN] Index Page News Preview Text')
)
created = models.DateField(
verbose_name=_('Release Date'),
blank=True
)
@property
def recent_posts(self):
two_months_before = timezone.now().date() - timedelta(days=60)
posts = NewsPostPage.objects.filter(created__gt=two_months_before)
return posts
content_panels = Page.content_panels + [
FieldPanel('news_title_en', classname='title full'),
RichTextFieldPanel('news_text_en'),
RichTextFieldPanel('preview_text_en'),
FieldPanel('created')
]
parent_page_types = ['NewsIndexPage']
class NewsIndexPage(Page):
news_index_title_en = models.CharField(
max_length=250,
verbose_name=_('[EN] News Index Title'),
blank=True,
default='',
)
news_index_image = models.ForeignKey(
'wagtailimages.Image',
related_name='+',
null=True,
on_delete=models.SET_NULL
)
content_panels = Page.content_panels + [
FieldPanel('news_index_title_en'),
ImageChooserPanel('news_index_image'),
]
subpage_types = ['NewsPostPage']
@property
def news_posts(self):
return self.get_children().live().specific()
@property
def recent_posts(self):
two_months_before = timezone.now().date() - timedelta(days=60)
posts = NewsPostPage.objects.filter(created__gt=two_months_before)
return posts
home/template
{% block content %}
<div id="kotak-news-events" class="kotak-grid">
<h4 class="title-strip title-kotak-bawah">Recent News and Events</h4>
<table>
{% for post in page.news_index.news_posts.all %}
<tr>
<td>{{ post.created }}</td>
<td>{{ post.translated_preview_text|richtext }}</td>
</tr>
{% endfor %}
</table>
</div>
{% endblock %}
I don't know how to insert the items in NewsPostPage to make it so that it shows in the home template. Thanks in advance
Upvotes: 1
Views: 227
Reputation: 91
It turns out you only need to add one property and I solved by adding a custom property as shown below:
class HomePage(Page):
why_choose_us_title_en = models.CharField(
verbose_name=_('[EN] Why Choose Us Title'),
max_length=200,
default='',
blank=True,
)
why_choose_us_subtitle_en = models.CharField(
verbose_name=_('[EN]Why Choose Us Subtitle'),
max_length=200,
default='',
blank=True,
)
content_panels = Page.content_panels + [
FieldPanel('why_choose_us_title_en', classname='full title'),
FieldPanel('why_choose_us_subtitle_en'),
]
subpage_types = [
'news.NewsIndexPage',
]
@property
def featured_products(self):
return ProductPage.objects.filter(featured=True)
# removed this line
# news_index = NewsIndexPage
# added this code
@property
def news_index(self):
return NewsPostPage.objects.live()
And still use this for the HTML
{% block content %}
<div id="kotak-news-events" class="kotak-grid">
<h4 class="title-strip title-kotak-bawah">Recent News and Events</h4>
<table>
{% for post in page.news_index.all %}
<tr>
<td>{{ post.created }}</td>
<td>{{ post.translated_preview_text|richtext }}</td>
</tr>
{% endfor %}
</table>
</div>
{% endblock %}
Upvotes: 1
Reputation: 1918
What you want to do is add additional context
to your template. Wagtail has this cool feature of mixing Views and Models together. So all you'd have to do is add your @properties
to the context
your sending to the template. Something like this:
class NewsIndexPage(Page):
template = 'templates/news_index_page.html'
@property
def news_posts(self):
return self.get_children().live()
@property
def recent_posts(self):
two_months_before = timezone.now().date() - timedelta(days=60)
posts = NewsPostPage.objects.filter(created__gt=two_months_before)
return posts
def get_context(self, request, *args, **kwargs):
"""Add posts to context"""
context = super().get_context(request)
context['recent_posts'] = self.recent_posts
context['news_posts'] = self.news_posts
return context
And because you're returning QuerySets to the template, you can loop through them normally. So your template would look something like this:
{% block content %}
<div id="kotak-news-events" class="kotak-grid">
<h4 class="title-strip title-kotak-bawah">Recent News and Events</h4>
<table>
{% for post in news_posts %} {# Notice the loop here #}
<tr>
<td>{{ post.created }}</td>
<td>{{ post.translated_preview_text|richtext }}</td>
</tr>
{% endfor %}
</table>
</div>
{% endblock %}
Upvotes: 2