CollectionType adds 2 rows on + click sonata - sonata-admin

I have extended sonata edit page with this:
{% extends '#SonataAdmin/CRUD/base_edit.html.twig' %}
{% block javascripts %}
{{ parent() }}
{{ encore_entry_script_tags('select2', null, 'admin') }}
{% endblock %}
But now when I click + button nera "Product option group codes" , it adds 2 rows.
If I remove
{{ encore_entry_script_tags('select2', null, 'admin') }}
then it works ok - adds just one row on + click.
I have commented all code in selec2.js file, to make sure it is not causing something but still nothing changes.
If I remove
parent()
Then "Product option group codes" js stops working.
How to debug? Where could be the problem?

Noticed that this js was not by sonata, but in our script. And when adding
{{ encore_entry_script_tags('select2', null, 'admin') }}
it calls document ready in another JS 2nd time, which setups + sign listener. So 2 listeners are set up.
To avoid this, instead of encore function, using script tag solved the problem. Also changed file name which I include.
{% extends '#SonataAdmin/CRUD/base_edit.html.twig' %}
{% block javascripts %}
{{ parent() }}
<script src="{{ asset('build/admin/admin-state-disaster-scenario.js', 'admin') }}"></script>
{% endblock %}

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

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 do I generate a list of pages in the sections for a sidemenu in Wagtail?

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 %}

{{ TWIG }} Define Dynamic Array Name

I am using {{TWIG}} with the Shopwired Platform. Hard coded into one of the templates is a gallery;
{# Render carousel #}
{% set gallery_name = 'global.theme.settings.gallery_location %}
This of course is working and great, however I would like to extend upon this and make some dynamic galleries for the site I am building.
I have figured out how to append/prepend the page title to build this;
{# Render carousel #}
{% set gallery_name = 'global.theme.settings.gallery_' ~ title|lower %}
{% set images = gallery_name %}
When I use {{ images }} to echo the result, it outputs the string name 'global.theme.settings.gallery_location' (which is correct for the page I am on) and not 'Array' as expected and desired.
The following, must be nearly right, but it only outputs one item from the array..
{# Render carousel #}
{% set gallery_name = 'global.theme.settings.gallery_' ~ title|lower %}
{% set images = [gallery_name] %}
I'm close.. what am I doing wrong?
To use dynamic keys, u can't relate on the dot notation to acces properties as the compiler can't handle that. Either use attribute or the array notation to access the data.
{% set arr = {
foo : {
bar : {
foobar : {
dynamic_index : 42,
}
}
}
} %}
{% set key = 'dynamic' %}
{{ attribute(arr['foo']['bar']['foobar'], key~'_index') }} {# 42 #}
{{ arr['foo']['bar']['foobar'][key~'_index'] }} {# 42 #}

Jinja2 in google appengine extended template repeates base templete

Ok I have a base.html and I try to use that for my header menu and footer. In my other template I loop over items and display them on the page. My problem is the the other template is repeating my base.html like it's in the loop. I hope someone can show me the error in My ways.
Here is my base.html code:
<div class="menu">
<ul class="nav">
<li>Home</li>
<li>New Entry</li>
<li>Sign-up</li>
{% if user %}
<li>{{user.name}}</li>
<li>Log-Out</li>
{% else %}
<li>Log-In</li>
{% endif %}
</ul>
​
This is in the base.html also but didn't paste correctly.
<div id="content">
{% block content %}
{% endblock %}
</div>
And here is the sub template code:
{% extends "base.html" %}
{% block content %}
{% for p in posts %}
{{ p.render() | safe }}
<br><br>
{% endfor %}
<div>
{{text}}
</div>
{% endblock %}
Please help
Edit:
edit2: removed link and found my problem I was calling the wrong html file in render()
Be kind Newbie here
Looks ok. Are you sure you don't have a loop in the python code that renders the template?

Resources