How do I generate a list of pages in the sections for a sidemenu in Wagtail? - django-models

I am a true beginner in Wagtail. How do I generate a list of pages in the sections for a sidemenu in Wagtail?
I have the following site structure, as an example:
home/
fruits/
apples/
oranges/
grapes/
vegetables/
kale/
spinach/
cabbage/
home is of HomePage type using home_page.html template , and all the subpages are of ContentPage type using content_page.html template.
I want to make a side menu for all the content pages, listing all the pages in their groups. For example, this list:
Fruits
Apples
Oranges
Grapes
should be the sidemenu for the pages fruits, apple, oranges, and grapes.
page.get_children in the template only lists out if the page has children, so, in this case just fruits and vegetables.
How would I go about making that sidemenu?
The examples in Wagtail's documentation seem to imply that I can't have just a generic content type like ContentPage to have the sort of listing that I want, is that true?
Thanks a bunch!

welcome to Wagtail!
As with most things in web development, there are a few ways you can do this. The simplest to understand when you're just starting is to do this all through the template. So in your home_page.html you could have:
{% for parent in page.get_children %}
Page title: {{ parent.title }} <br />
{% if parent.get_children.count %}
{% for child in parent.get_children %}
- Child page title: {{ child.title }}<br/>
{% endfor %}
{% endif %}
{% endfor %}
What this does is:
Loops through the child pages of HomePage (labeled as parent in this loop) and prints Page title: {title_here}
Then it'll check for child pages of each parent loop iteration and print - Child page title: {child_title}
There's a gotcha here though. This will only work on the home_page.html template. Once you go to /fruits/ it'll try to perform the same logic, but this time it'll think Fruits is the new HomePage
There are 2 options you can take from here.
You can add custom context to every page to make sure you're always passing in the HomePage and loop through that. This is the simplest method and I'll show you the code below. Or,
You can create a Menu system using a Django Model and registering the Menu class as a Wagtail Snippet. I have a video with all the source code available if you want to take a deeper dive into Wagtail (https://www.youtube.com/watch?v=Y8a9ROUUJXU)
To add HomePage to every ContentPage you can add it to the context of every page, like so:
class ContentPage(Page):
# Fields here
def get_context(self, request, *args, **kwargs):
"""Adding HomePage to your page context."""
context = super().get_context(request, *args, **kwargs)
context["home_page"] = HomePage.objects.first()
return context
And in your templates you'd write:
{% for child_page in home_page.get_children %}
Page title: {{ child_page.title }} <br />
{% if child_page.get_children.count %}
{% for grandchild_page in child_page.get_children %}
- Child page title: {{ grandchild_page.title }}<br/>
{% endfor %}
{% endif %}
{% endfor %}
Edit: If you're on a grandchild page, like /fruits/apples/ and want to display the parent page title, and all the sibling pages (ie. /fruits/oranges/ and /fruits/grapes/) you can loop through the sibling pages. Something like this should work:
<!-- On `/fruits/` this will be the Home Page title. On `/fruits/apples/` this will be the Fruits page title. -->
<h2>{{ self.get_parent.title }}<h2>
{% for sibling in self.get_siblings %}
{{ sibling.title }}
{% endfor %}

Related

How can you loop through all of the children of a model?

In Django I am trying to loop through all of the children of my Todo model. But whenever I try to run it, it gives me an AttributeError that says "Manager isn't accessible via Todo instances". My code looks like this:
{% extends 'base.html' %}
{% block content %}
<h3>Tasks</h3>
{% for t in model.objects.all %} <!-- Error -->
<p>{{t.name}}</p>
{% endfor %}
{% endblock %}
{% block options %}
<li class="bg-light py-3 w-100 px-4 rounded text-nowrap fs-4">
<button class="text-decoration-none text-dark">Save</button>
</li>
{% endblock %}
I tried to just put the model in the context, and then I got an error in the HTML, so I figured out that it happened when I tried to reference 'model.objects.all'.
Inside of your view you need to specify what django should pass to the template. It does not serve the entire Database; therefore queries like in model.objects.all inside of your templates are not allowed.
Specify the queryset inside your views.py:
def todo_view(request):
context = {}
context['my_todos'] = my_todo_model.objects.all()
context['most_important_todo'] = my_todo_model.objects.get(pk=1)
# put your own logic inside the `.get` method above
return render(request, 'my_template.html' context)
And then access it inside of your template like so:
{% for t in my_todos %}
<p>{{ t.name }}</p>
{% endfor %}
{{ most_important_todo.name }}
Because we put a queryset inside of my_todos we can loop over it in the template. most_important_todo ist just a single object passed to the template, so we can access its properties (e.g. the name) directly.
Let me know how it goes

how to pass django params in react components

i am new to react , i am building simple blog where user can post with title and body
in html its done with listview with:
{% for x in object_list %}
{% endfor %}
but in react component its not getting good result and showing error
here is my code:
models
class post(models.Model):
title = models.CharField(max_length=100)
body=models.TextField()
views
class list(ListView):
model = post
template_name = 'index.html'
post.js
function Post(){
return(
{% for x in object_list %}
{% endfor %}
)
}
in react what can i do to retreive data from model like we used to do in normal html, or show the object from model in components??

HubL / Twig: Not finding value from array

In HubSpot, I've created a custom module called footer. footer has five field types of menu:
I've created an array where all five of the above menu ID's are pushed to an array. I've done this via a template partial file which is included in my footer module.
<!-- creating array -->
{% set footer_id_array = [] %}
<!-- push menu id's to array -->
{% do footer_id_array.append(module.menus.menu_column_1) %}
{% do footer_id_array.append(module.menus.menu_column_2) %}
{% do footer_id_array.append(module.menus.menu_column_3) %}
{% do footer_id_array.append(module.menus.menu_column_4) %}
{% do footer_id_array.append(module.menus.menu_column_5) %}
Running {{ footer_id_array }} shows all the IDs in the array, i.e.
[29420054435, 29420223163, 29420054590, 29420158158, 29420071857]
So this is correct, the array contains the IDs.
Now, for each item in this array, I want to generate a nav, so in my footer custom module, I have the following:
{% set iterations = range(0, 5) %}
{% for i in iterations %}
<nav>
{% menu id="{{ footer_id_array[i] }}" %}
</nav>
{% endfor %}
However, on my page, this just prints HubSpots default menus, not the ones assigned to the ID's.
Why is this?

How to access default page models in template wagtail

So this awesome Wagtail/Django framework is nice!
I like it allot.
Still getting used to but seems straight forward,
What I do not understand tho is how can I access default page models and render them in the templates?
So Wagtail has this models that you make based on their Page class.
class SomeClass(Page):
"""
Some text
"""
intro = models.CharField(max_length=255, blank=True)
body_small = models.CharField(max_length=255, blank=True)
All good and well.
Now my page template looks like this
{% extends "base.html" %}
{% load wagtailcore_tags %}
{% block base_content %}
{{ page.intro }}
{{ page.body_small }}
{% endblock %}
Now I want to add the settings model items like Published Date.
Those are default from Wagtail, see:
What page model do I need to use?
{{ page.published_date }} //Does not work
Any suggestions?
The fields in the Settings tab are available as {{ page.go_live_at }} and {{ page.expire_at }}. However, these are only used for scheduled publishing so may not be a particularly relevant thing to output on the page - {{ page.first_published_at }} and {{ page.last_published_at }} are probably more useful. See http://docs.wagtail.io/en/stable/reference/pages/model_reference.html for more.

mean io swig block inside view

I'm using mean stack and have a problem with doing a basic thing like placing content in a block defined in the main layout.
What i have:
MyProjectName/packages/core/system/server/views/layouts/default.html
<div id="content-right" class="">
{% block content-right %}{% endblock %}
</div>
MyProjectName/packages/custom/custompackagename/public/views/list.html
{% block content-right %}
Lorem ipsum
{% endblock %}
Instead of showing the content of "content-right" block (Lorem ipsum in this case) it shows the whole thing as a string, hence not working, the block is not rendered, not processed however mean works.
I found that MyProjectName/packages/core/system/server/views/index.html is used everywhere so if i place the block content snippet there it works. I dont want that because the stuff isnide the block should be according to the page where i am at, not same on every page. How do i achieve that? Its basic stuff, why would one .html file template render dynamic content as it should be and another is served like static...
For anyone wondering the same thing, here is what i've found
as per http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.directive:ui-view we can create multiple named views inside our router file in MEAN IO stack that is MyProjectName/packages/custom/custompackagename/public/routes/custompackage.js
Here is an example of a state with two views
$stateProvider
.state('all projects', {
url: '/mypackage',
views: {
"" : {
templateUrl: '/mypackage/views/list.html'
},
"content-right" : {
templateUrl: '/mypackage/views/content-right.html'
}
}
})
I've "declared" the position of my custom view inside the main layout file
MyProjectName/packages/core/system/server/views/layouts/default.html
<div id="content-right" class="">
{% block content-right %}{% endblock %}
</div>
Then modify MyProjectName/packages/core/system/server/views/index.html to include the new named ui-view that we created inside the public router file
{% block content-right %}
<section data-ui-view="content-right"></section>
{% endblock %}
Then create the file specified inside the public router file for the view, in this case /mypackage/views/content-right.html had put your content there, refresh page, it works.

Resources