Jinja2: update a document and preserve the updating directive for further updates - templates

I need a part of a document's content to be updated. The document looks as follows:
There is some text.
{# alpha.txt begins here #}
...
{# alpha.txt ends here #}
There is some text.
{# bravo.txt begins here #}
...
{# bravo.txt ends here #}
There is some text.
{# charlie.txt begins here #}
...
{# charlie.txt ends here #}
There is some text.
I need this file to be updated with the content of the alpha.txt, bravo.txt and charlie.txt files. The document could be updated by a third party, so I can't just re-render this document from a template, I rather need it to be carefully updated with the content of these files.
Is there a way to do that?
Thank you.

Related

How to setup a custom form/page within EasyAdminBundle

I have been able to build a simple CRUD app for a project using the Symfony EasyAdminBundle and it has worked great for the normal entity based use cases. I have some additional use cases though where I want to do things like rebuilding data. For these I have to capture certain request attributes, pass over to a controller and then delegate to a backend API call to a remote service.
This can all be done in Symfony but I am running into trouble with how to wire this into the EasyAdmin view/method of working. Ideally I want this to be a page inside easy admin and not lose the left menu etc. So far, the only way I have found to do this is to create a Model class what is using one of the existing tables but has only some properties I would need to drive into the API. I then override the controller actions so rather than do a default save, I handle against that remote API.
The problem with this approach is that obviously I am now bound to Doctrine entities and that would be problematic for requests that were not mappable to the database.
Is there a way to define a logical entity that would let me leverage associations so I can have lookups etc, that will wire into the bundle seamlessly, but are not actually tied to a backend database table or view?
I am adding my response for people who may still face this issue in the future.
How I solved this without creating an entity :
Create a custom controller: symfony console make:controller
Edit the controller's view to inherit the EasyAdmin layout :
{# ./src/templates/home/index.html.twig #}
{% extends '#EasyAdmin/Default/layout.html.twig' %}
{# Let\'s remove/empty the header #}
{% block content_header_wrapper %} {% endblock content_header_wrapper %}
{# The main page content block #}
{% block main %}
**PUT YOUR CODE HERE**
{% endblock main %}
{# Let\'s remove/empty the footer #}
{% block content_footer_wrapper %} {% endblock content_footer_wrapper %}
Add your page to the side navigation
design:
menu:
- {route: 'home', label: 'Home', default: true, icon: 'home'}
- {entity: 'MyEntity', label: 'My Relevant Entity', icon: 'briefcase'}
I'd solve this problem creating a custom action as explained here (probably you want a route-based action) and then use a template that extends from #EasyAdmin\default\layout.html.twig or any other default template similar to what you want to achieve.
Here is solution:
{# easy_admin/form.html.twig #}
{% block _product_custom_title_widget %}
{# ... #}
More information
{% endblock %}
Finally, add this custom theme to the list of themes used to render backend forms:
easy_admin:
# ...
design:
form_theme:
- 'horizontal'
# the following Twig template can be located anywhere in the application.
# it can also be added to the twig.form_themes option to use it in the
# entire application, not only the backend
- 'easy_admin/form.html.twig'
Here is link for more information: https://symfony.com/doc/master/bundles/EasyAdminBundle/book/edit-new-configuration.html
Easyadmin is a bundle and you can customize all the pages of any bundle.
This logic applies to any template that lives in a bundle: just follow the convention: app/Resources/{BUNDLE_NAME}/views/{PATH/TO/TEMPLATE.html.twig}.
Suppose you've installed an imaginary open-source AcmeBlogBundle in your project. And while you're really happy with everything, you want to override the template for a blog list page. Inside the bundle, the template you want to override lives at Resources/views/Blog/index.html.twig.
To override the bundle template, just copy the index.html.twig template from the bundle to app/Resources/AcmeBlogBundle/views/Blog/index.html.twig (the app/Resources/AcmeBlogBundle directory won't exist, so you'll need to create it). You're now free to customize the template.
Reference: https://symfony.com/doc/3.4/templating/overriding.html

Capture and append in Twig

What I need is to append text blocks to the same name in any template and finally print its value.
What I have so far.
In child template:
{% set tmp %}
...some text...
{% endset %}
{% set capture = capture|default([])|merge([tmp]) %}
In parent (main layout):
{{ capture|default([])|join|raw }}
{# it works in the same template but not in parent #}
I know it is ugly but still would be happy if it worked.
Ideally I'd like to make an extension to work like this:
{% capture %}
...some text...
{% endcapture %}
{# to capture #}
{% capture() %}
{# to print #}
but documentation that I've seen (http://twig.sensiolabs.org/doc/advanced.html) does not help.
I don't know what type of extension should I choose, where actual data manipulations are made, how I access and append data.
What existing extension could I use as a base?
Couldn't access even Twig global variable set in sf config.
So created 2 Twig functions: one to append content, another to get what is buffered.
Using twig extension class property as "global var" because container params turned out to be locked.
Usage:
set content to local var
append local var to global var
get and print raw global var content

Django-CMS - Global placeholder?

Is there any way to make global placeholder in my base template? I need it to be the same on every page (banners list).
How can I do that?
I usually create a page in my CMS that isn't published, but contains placeholders that I would like to use elsewhere (footer/headers) etc.
Make a new template extra_placeholders.html:
{% extends "base.html" %}
{% load cms_tags %}
{% block content %}
{% placeholder "Banner-List" %}
{% endblock %}
add it to your settings:
CMS_TEMPLATES = (
('my/path/extra_placeholders.html', 'Extra Placeholder Page'),
...
)
now go to the admin and create the placeholder with whatever plugin you want. Then go to you base template (*base.html probably) from which all your other pages inherit and add this wherever you want the placeholder to appear:
{% load cms_tags %}
...
{% show_placeholder "Banner-List" "extra_placeholders" %}
You can read more about it in the docs
EDIT
As #José L. Patiño has mentioned in the comments, this solution is only necessary for those using django-cms < 3.0. For the newer version you can simply use the static_placeholder template tag
There is the "static_placeholders" now, http://docs.django-cms.org/en/latest/reference/templatetags.html#static-placeholder
Sounds like it's what you needed way back when.
You can use the following ways to create a global palceholder for all pages.
create a place holder on the base page. {% Placeholder "footer"%}
make the contents of the placeholder through django cms as home page
then to display the same for each placeholder page, add {% show_placeholder "footer" "home"%}, this means displaying the newly created footer placeholder earlier from the home page,
This will display the entire contents existing footer placeholders on the home page of all pages that use the template.
but for the home page there will be two footer is displayed, to mengilangkannya, please do modifications to use CSS to hide the master placeholder.

Can a django template be referenced from within a loop on another template?

I have a django template which loops over many notes/comments. As a simplified example take this.
{% for note in notes %}
<p>
Date added: {{ note.date_added }}
{{ note.note|urlize|url_target_blank|linebreaks }}
</p>
{% endfor %}
Then on the same page I have a form to add a new note. This note form is an ajax form and returns the newly submitted note back to the page and appends it at the end of the already existent note area.
I don't like this because I have to maintain the same html structure both in the page for the initial load, as well as in the response from the ajax form.
Is there a way to put a call to another template, inside of a template (in this for loop) so I can maintain the note formatting in one location only?
Thanks.
Perhaps you're looking for the "include" tag: http://docs.djangoproject.com/en/dev/ref/templates/builtins/#include

Django conditional template inheritance

I have template that displays object elements with hyperlinks to other parts of my site. I have another function that displays past versions of the same object. In this display, I don't want the hyperlinks.
I'm under the assumption that I can't dynamically switch off the hyperlinks, so I've included both versions in the same template. I use an if statement to either display the hyperlinked version or the plain text version. I prefer to keep them in the same template because if I need to change the format of one, it will be easy to apply it to the other right there.
The template extends framework.html. Framework has a breadcrumb system and it extends base.html. Base has a simple top menu system.
So here's my dilemma. When viewing the standard hyperlink data, I want to see the top menu and the breadcrumbs. But when viewing the past version plain text data, I only want the data, no menu, no breadcrumbs. I'm unsure if this is possible given my current design. I tried having framework inherit the primary template so that I could choose to call either framework (and display the breadcrumbs), or the template itself, thus skipping the breadcrumbs, but I want framework.html available for other templates as well. If framework.html extends a specific template, I lose the ability to display it in other templates.
I tried writing an if statement that would display a the top_menu block and the nav_menu block from base.html and framework.html respectively. This would overwrite their blocks and allow me to turn off those elements conditional on the if. Unfortunately, it doesn't appear to be conditional; if the block elements are in the template at all, surrounded by an if or not, I lose the menus.
I thought about using {% include %} to pick up the breadcrumbs and a split out top menu. In that case though, I'll have to include it all the time. No more inheritance. Is this the best option given my requirement?
You can put your hyperlinks inside a block that is overridden by the loading templates.
Let's say you have your framework.html like this:
{% extends "base.html" %}
<html>...<body>...
{% block hyperlinks %}
your hyperlinks here
{% endblock %}
rest of the code
</body></html>
You can then create something of a nolinks.html template and use it
{% extends "framework.html" %}
{# here you'll have everything from framework
but now we disable the breadcrumbs #}
{% block hyperlinks %}{% endblock %}
If you're getting the past data you can then use nolinks to render instead of framework.
I hope this helps.
From here: Any way to make {% extends '...' %} conditional? - Django
It can be done like this :
{% extends ajax|yesno:"ajax_base.html,main_base.html" %}
Or:
{% extends a_variable_containing_base_template_name %}
Which ever best suited for you.
Regards;