Phalcon Volt - Multiple Inheritance - templates

Is there any way to use multiple inheritance in PhalconPHP Volt?
I'd like to do something like that:
// index.volt
<!DOCTYPE html>
<html>
<head>
...
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
Next:
// layout.volt
{% extends 'index.volt' %}
{% block content %}
<div class='header'><div>
{% block actionContent %}{% endblock %}
<div class='footer'><div>
{% endblock %}
And then:
// actionView.volt
{% extends 'layout.volt' %}
{% block actionContent %}
Lorem Ipsum
{% endblock %}
It doesn't work because of Embedding blocks into other blocks is not supported...
I very want resolve this problem. Is it possible?

This is not supported yet. But over on Github I see there are two tickets open for this issue:
[VOLT] Support for embedding blocks into other blocks
https://github.com/phalcon/cphalcon/issues/329
Volt parser embedding block error
https://github.com/phalcon/cphalcon/issues/12846
Might be a good idea to bump one of those issues to see if there has been an update.

The only way I see here is instead of extending parent volts, you can include the children. That is supported.
// layout.volt
{% extends 'index.volt' %}
{% block content %}
<div class='header'><div>
{% include 'actionView.volt' %}
<div class='footer'><div>
{% endblock %}
and
// actionView.volt
Lorem Ipsum

Related

Unable to load multiple content blocks in Django 4.0 using TailwindCSS

Folder Structure:
mysite
-theme
--templates
---main_base.html
---theme_footer.html
---theme_menu.html
-home
--templates
---home
----main.html
main.html:
{% extends "main_base.html" %}
{% block content %}
blah blah
{% end content %}
main_base.html:
{% load static tailwind_tags %}
<!DOCTYPE html>
<html lang="en">
<head>
{% tailwind_css %}
</head>
<body class="bg-blue-100">
<nav>
{% block navbarn %}
{% endblock %}
</nav>
{% block content %}
{% endblock %}
<footer>
{% block footer %}
{% endblock %}
</footer>
</body>
</html>
theme_menu.html:
{% extends "main_base.html" %}
{% block navbarn %}
home
{% endblock %}
theme_footer.html
{% extends "main_base.html" %}
{% block footer %}
<h1>this is a footer</h1>
{% endblock %}
So I was able to setup Django with Tailwind following the instructions on the plugin page. But I can't get the base theme to show multiple blocks. It doesn't show the menu nor the footer, just the base html template with content from main.html. Can't get it to work!
If anyone else is running into this issue, you can't use multiple extends. You instead, include it in your base.
For me, I removed the {% extends %} tags from the ancillary pages, and then included them in my theme_base.html like:{% include 'theme_footer.html' %}

Is it okay to have two base.html templates in django?

Is it okay to have multiple base.html templates in django? For instance, I would have one template that would extend from base_one.html and another template extending from base_two.html. For example, this is one of the templates:
{% extends "base_one.html" %}
{% block content %}
{% endblock content %}
and this is another template:
{% extends "base_two.html" %}
{% block content %}
{% endblock content %}
Well not only two you can keep how much you want just with different names and you have to extend on different templates but yeah you can easily keep parts of the base template and extend in one according to your needs.
I'm adding three files here 1-base.html 2-base-comments.html 3-post-template.html
Here is a little expansion of my answer
Suppose this file name is base.html
# base.html
<html>
<head>
<title>Foo</title>
</head>
<body>
<header>
{% block header %}
<h1>Lorem ipsum</h1>
{% endblock %}
</header>
{% block content %}{% comment %}A wrapper around content is needed{% endcomment %}
<div class="page-content">
{% block page_content %}{% comment %} Filled in by your page templates {% endcomment %}
{% endblock %}
</div>
{% endblock %}
<footer>
{% block footer %}
<em>♥ joar</em>
{% endblock footer %}
</footer>
</body>
</html>
here is another file base-comments.html which extends the previous file.
# base-comments.html
{% extends 'base.html' %}
{% block content %}
<div class="page-content">
{% block page_content %}{% comment %} Filled in by your page templates {% endcomment %}
{% endblock %}
{% block comments %}
<footer>
<h2>Comments</h2>
<script>loadCommentsEtc()</script>
</footer>
{% endblock %}
</div>
{% endblock %}
And here is the last file which extends the 2nd base file which already extends the 1st base file 3-post-template.html
# post-template.html
{% extends 'base-comments.html' %}
{% block page_content %}
<article>
<h1>{{ post.title }}</h1>
<div class="post-body">
{{ post.body }}
</div>
</article>
{% endblock %}
I hope this works and clears your doubts.
Thanks for the question.

Strip HTML from Django template block?

In my Django base.html template I have a title block:
<html>
<head>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
{% block content %}
{% endblock %}
</body>
</html>
In a page template I use the text from its <h1> page title in that block, so it also appears in the <title> tag, e.g.:
{% extends 'base.html' %}
{% block content %}
<h1>{% block title %}Hello world!{% endblock %}</h1>
{% endblock %}
That all works fine. But if I want to use HTML tags within the page's <h1> like this...
{% extends 'base.html' %}
{% block content %}
{% block title %}<b>Hello</b> world!{% endblock %}
{% endblock %}
...those tags will also appear in the <title>, which isn't allowed.
Is there a way around this other than having two versions of the title: one within <h1>, and one HTML-free version within a {% block title %}? I don't think there's a way to strip HTML from a block?
You could use cycle like so:
{% extends 'base.html' %}
{% block content %}
<h1>
{% block title %}
{% cycle '' '<b>' %}Hello world!{% cycle '' '</b>' %}
{% endblock %}
</h1>
{% endblock %}
Hope this helps

How to display layout content in Twig template based on a view

I have some content in my layout that are not supposed to be displayed in some pages.
E.g.: When a user is registering for the site my default frontpage sidebar should not be displayed:
<!DOCTYPE html>
<html>
<head>
{% block head %}
<link rel="stylesheet" href="style.css" />
<title>{% block title %}{% endblock %} - My Webpage</title>
{% endblock %}
</head>
<body>
<div id="content">
<div id="sidebar">
{% block sidebar %}
{% render "/layout/sidebar" %}
{% endblock %}
{% block content %}{% endblock %}
</div>
</div>
<div id="footer">
{% block footer %}
© Copyright 2011 by you.
{% endblock %}
</div>
</body>
</html>
In the above code:
{% block sidebar %}
should display some advertising instead!
So:
Something like:
{% if SOMEVIEW == TRUE %}
{% block sidebar %}
{% else %}
{% block advertising %}
{% endif %}
What expression could I use in my IF to accomplish that job?
Thanks in advance
You can look at
How to check if an user is logged in Symfony2 inside a controller?
and http://symfony.com/doc/current/book/security.html#access-control-in-templates
In the view you can use {{ is_granted('IS_AUTHENTICATED_FULLY') }} to check if a user is logged in.
Hope it's helpful.
Best regard.
I came accross to the solution here http://symfony.com/doc/current/cmf/bundles/core.html#twig:
app.request.attributes.get('_template').get('name')
will return the route name so that I can handle it inside my twig files.

How to repeat a "block" in a django template

I want to use the same {% block %} twice in the same django template. I want this block to appear more than once in my base template:
# base.html
<html>
<head>
<title>{% block title %}My Cool Website{% endblock %}</title>
</head>
<body>
<h1>{% block title %}My Cool Website{% endblock %}</h1>
</body>
</html>
And then extend it:
# blog.html
{% extends 'base.html' %}
{% block title %}My Blog{% endblock %}
# pictures.html
{% extends 'base.html' %}
{% block title %}My Pictures{% endblock %}
# cats.html
{% extends 'base.html' %}
{% block title %}My Cats{% endblock %}
I will get an exception, as Django wants the block to appear only once:
TemplateSyntaxError at /
'block' tag with name 'title' appears
more than once
A quick and dirty solution would be duplicating the block title into title1 and title2:
# blog.html
{% extends 'base.html' %}
{% block title1 %}My Blog{% endblock %}
{% block title2 %}My Blog{% endblock %}
But this is a violation of the DRY principle. It would be very difficult as I have a lot of inheriting templates, and also because I don't wanna go to hell ;-)
Is there any trick or work-around to this problem? How can I repeat the same block in my template, without duplicating all the code?
Use the Django template macros plugin:
https://gist.github.com/1715202 (django >= 1.4)
or
http://www.djangosnippets.org/snippets/363/ (django < 1.4)
django >= 1.4
# base.html
{% kwacro title %}
{% block title %}My Cool Website{% endblock %}
{% endkwacro %}
<html>
<head>
<title>{% usekwacro title %}</title>
</head>
<body>
<h1>{% usekwacro title %}</h1>
</body>
</html>
and
# blog.html
{% extends 'base.html' %}
{% block title %}My Blog{% endblock %}
django < 1.4
# base.html
{% macro title %}
{% block title %}My Cool Website{% endblock %}
{% endmacro %}
<html>
<head>
<title>{% usemacro title %}</title>
</head>
<body>
<h1>{% usemacro title %}</h1>
</body>
</html>
and
# blog.html
{% extends 'base.html' %}
{% block title %}My Blog{% endblock %}
I think that use of the context processor is in this case an overkill. You can easily do this:
#base.html
<html>
<head>
<title>{% block title %}My Cool Website{% endblock %}</title>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
and then:
# blog.html
{% extends 'base.html' %}
{% block content %}
<h1>{% block title %}My Blog{% endblock %}</h1>
Lorem ipsum here...
{% endblock %}
and so on... Looks like DRY-compatible.
You probably don't actually want to use a block but rather to just use a variable:
# base.html
<html>
<head>
<title>{{ title|default:"My Cool Website" }}</title>
</head>
<body>
<h1>{{ title|default:"My Cool Website" }}</h1>
</body>
</html>
You then set the title through the context.
Here's a way I discovered when trying to do the same thing myself:
# base_helper.html
<html>
<head>
<title>{% block _title1 %}{% endblock %}</title>
</head>
<body>
<h1>{% block _title2 %}{% endblock %}</h1>
</body>
</html>
# base.html
{% extends "base_helper.html" %}
# Copy title into _title1 & _title2, using "My Cool Website" as a default.
{% block _title1 %}{% block _title2 %}{% block title %}My Cool Website{% endblock %}{% endblock %}{% endblock %}
Requires an extra file unfortunately, but doesn't require you to pass the title from the view.
you can use {% include subtemplate.html %} more than once. it's not the same as blocks, but does the trick.
There are some discussion here:
http://code.djangoproject.com/ticket/4529
Obviously django core team reject this ticket because they think this is not a common used scenario, however I disagree.
repeat block is simple and clean implementation for this:
https://github.com/SmileyChris/django-repeatblock
template macros is another one, however the author mentioned it's not carefully tested:
http://www.djangosnippets.org/snippets/363/
I used repeatblock.
As an update for anyone coming across this, I've taken the snippet mentioned above and turned it into a template tag library, django-macros, makes the macros more powerful and also implements a repeated block pattern explicitly: django-macros.
Here is a lightweight solution similar to the above do_set and do_get template tag answer. Django allows you to pass the entire template context into a tag which can allow you to define a global variable.
base.html:
<!DOCTYPE html>
<html lang="en">
<head>
{% block head %}
<title>{{ title }}</title>
{% endblock %}
</head>
<body>
<h1>{{ title }}</h1>
</body>
</html>
page.html:
{% extends "base.html" %}
{% block head %}
{% define 'title' 'Homepage | title' %}
{{ block.super }}
{% endblock %}
custom tag (got the idea here: https://stackoverflow.com/a/33564990/2747924):
#register.simple_tag(takes_context=True)
def define(context, key, value):
context.dicts[0][key] = value
return ''
Also don't forget to {% load %} your custom tags or add them to the template options builtins list so you don't have to load them in every template. The only limitation to this approach is the {% define %} has to be called from within a block tag because child templates only render block tags that match the parent tags. Not sure if there is a way around that. Also make sure the define call comes before you try to use it obviously.
Building on Van Gale's suggestion, you could create get and set tags by adding the following to your templatetags.py file:
register = template.Library()
Stateful = {}
def do_set(parser, token):
_, key = token.split_contents()
nodelist = parser.parse(('endset',))
parser.delete_first_token() # from the example -- why?
return SetStatefulNode(key,nodelist)
class SetStatefulNode(template.Node):
def __init__(self, key, nodes):
Stateful[key] = nodes
def render(self, context):
return ''
register.tag('set', do_set)
def do_get(parser, token):
tag_name, key = token.split_contents()
return GetStatefulNode(key)
class GetStatefulNode(template.Node):
def __init__(self, key):
self.key = key
def render(self, context):
return ''.join( [x.render(context) for x in Stateful[self.key]] )
register.tag('get', do_get)
Then set values in one template via {% set foo %}put data here{% endset %} and get them via {% get foo %} in another.
I too have come across the same need for a repeated {% block %} in my template files. The issue is that I want a Django {% block %} to be used in either case of a Django conditional, and I want the {% block %} to be over-writable by subsequent files that may extend the current file. (So in this case, what I want is definitely more of a block than a variable because I'm not technically re-using it, it just appears on either end of a conditional.
The Problem:
The following Django template code will result in a Template Syntax Error, but I think it's a valid "want" to have a defined {% block %} re-used in a conditional (IE, why is the Django parser validating syntax on BOTH ends of a conditional, shouldn't it only validate the TRUTHY condition?)
# This example shows a {{ DEBUG }} conditional that loads
# Uncompressed JavaScript files if TRUE
# and loads Asynchronous minified JavaScript files if FALSE.
# BASE.html
{% if DEBUG %}
<script src="{{MEDIA_URL}}js/flatfile.1.js"></script>
<script src="{{MEDIA_URL}}js/flatfile.2.js"></script>
<script src="{{MEDIA_URL}}js/flatfile.3.js"></script>
<script type="text/javascript">
{% block page_js %}
var page = new $site.Page();
{% endblock page_js %}
</script>
{% else %}
<script type="text/javascript">
// load in the PRODUCTION VERSION of the site
// minified and asynchronosly loaded
yepnope([
{
load : '{MEDIA_URL}}js/flatfiles.min.js',
wait : true,
complete : function() {
{% block page_js %} // NOTE THE PAGE_JS BLOCK
var page = new $site.Page();
{% endblock page_js %}
}
}
)];
</script>
{% endif %}
# ABOUT.html
{% extends 'pages/base.html' %}
{% block page_js %}
var page = new $site.Page.About();
{% endblock page_js %}
The Solution:
You can use an {% include %} to conditionally insert a {% block %} more than once. This worked for me because the Django syntax checker includes only the TRUTHY {% include %}. See the result below:
# partials/page.js
{% block page_js %}
var page = new $site.Page();
{% endblock %}
# base.html
{% if DEBUG %}
<script src="{{MEDIA_URL}}js/flatfile.1.js"></script>
<script src="{{MEDIA_URL}}js/flatfile.2.js"></script>
<script src="{{MEDIA_URL}}js/flatfile.3.js"></script>
<script type="text/javascript">
{% include 'partials/page_js.html' %}
</script>
{% else %}
<script type="text/javascript">
yepnope([
{
load : '{MEDIA_URL}}js/flatfiles.min.js',
wait : true,
complete : function() {
{% include 'partials/page_js.html' %}
}
}
)];
</script>
{% endif %}
I use this answer to keep things dry.
{% extends "base.html" %}
{% with "Entry Title" as title %}
{% block title %}{{ title }}{% endblock %}
{% block h1 %}{{ title }}{% endblock %}
{% endwith %}
There are two easy solutions for this.
The easiest is to put your title into a context variable. You would set the context variable in your view.
If you are using something like generic views and don't have a views.py for pictures, cats, etc. then you can go the way of a custom template tag that sets a variable in the context.
Going this route would enable you to do something like:
{% extends "base.html" %}
{% load set_page_title %}
{% page_title "My Pictures" %}
...
Then in your base.html:
...
{% block title %}{{ page_title }}{% endblock %}
...
<h1>{{ page_title }}</h1>
The selected answer alludes to an easy workaround to wrap one tag inside another in the child template to give them both the same value. I use this for social images like so.
Child template:
{% extends 'base.html' %}
...
{% block meta_image %}
{% block meta_image_secure %}
{% if object.cover_pic %}
{{ object.cover_pic.url }}
{% else %}
https://live-static.welovemicro.com/static/img/device-dark.png
{% endif %}
{% endblock %}
{% endblock %}
...
Then in the parent base.html:
...
<meta property="og:image" itemprop="image" content="{% block meta_image %}https://live-static.welovemicro.com/static/img/device-dark.png{% endblock %}">
<meta property="og:image:secure_url" itemprop="image" content="{% block meta_image_secure %}https://live-static.welovemicro.com/static/img/device-dark.png{% endblock %}">
...
I would suggest using the django-macros library.
To install:
pip install django-macros
And then add the 'macros' app in your INSTALLED_APPS list in settings.py.
After that, load the macros custom tags in your base template and use them like that:
{# base.html #}
{% load macros %}
{% macro title %}
{% block title %} My Cool Website {% endblock %}
{% endmacro %}
<html>
<head>
<title> {% use_macro title %} </title>
</head>
<body>
<h1> {% use_macro title %} </h1>
</body>
</html>
In twig you can make this like:
# base.html
<html>
<head>
<title>{{ block('title') }}</title>
</head>
<body>
<h1>{{ block('title') }}</h1>
</body>
</html>
# blog.html
{% extends 'base.html' %}
{% block title %}My Blog{% endblock %}
# pictures.html
{% extends 'base.html' %}
{% block title %}My Pictures{% endblock %}
# cats.html
{% extends 'base.html' %}
{% block title %}My Cats{% endblock %}