How to render two or more templates? - django-templates

I have two templates to render in my django project:
This is template 'b.html'
<html>
<body>
{% include 'a.html' %}
{{ userName}}
</body>
</html>
and it's the 'a.html':
{{ another_name}}
And I'm finishing tasks and return userName to 'b.html' and another_name to 'a.html',what should I do?Should use render_to_response?Thank you~

You can take a look at the doc for the include tag : https://docs.djangoproject.com/en/1.8/ref/templates/builtins/#include
And you can use render_to_response() to render your template :
return render_to_response('b.html', {
'userName': 'a',
'another_name': 'b'
}

Related

display link_list menu on certain pages

I'd like to get a certain menu to display in the header on my product page instead of site-wide.
my theme.liquid file has the {% section 'header' %} tag within the <body> so my header is showing fine on all pages as expected.
the sections/header.liquid has the following schema:
{% schema %}
{
"name": "Header",
"settings": [
{
"type": "link_list",
"id": "menu",
"default": "main-menu",
"label": "Heading Navigation Menu"
}
]
}
{% endschema %}
I thought when you go into the theme editor on Shopify that you'd be able to individually select what shows up in the in menu part of my 'Heading Navigation Menu' section per page (Home, Collections, Blog, etc.), but at this point it's static. Ideally I'd be able to go in there and select a different menu I create in the Navigation setting for certain pages.
I ended up handling this with a switch statement and the template object.
In my navigation bar in my sections/header.liquid I created the switch statement:
<nav>
<ul>
{% case template.name %}
{% when 'article' %}
<li>
Show that
</li>
{% when 'cart' or 'blog' or 'product' %}
<li>
Show that and this
</li>
{% else %}
<li>
Show this
</li>
{% endcase %}
</ul>
</nav>
You can put whatever element you like inside of the individual cases and it will check whatever your template name is to put display that element.
Shopify documentation for both:
template object
switch statement
Not sure if this is the most effective way to do this, but hope this helps anyone trying to accomplish something similar.

What is correct way of inserting wagtail streamfield block dependencies into the template?

I rely on template inheritance system to insert extra_css and/or extra_js into my pages:
base.html:
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Core CSS -->
{% block extra_css %}
{# Override this in templates to add extra stylesheets #}
{% endblock %}
</head>
<body>
{% block content %}{% endblock content %}
<!-- Core JS -->
{% block extra_js %}
{# Override this in templates to add extra javascript #}
{% endblock extra_js %}
</body>
</html>
page.html:
{% extends "base.html" %}
{% block extra_css %}
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css" rel="stylesheet" />
{% endblock %}
{% load wagtailcore_tags wagtailimages_tags %}
{% block content %}
<div class="blog-post">
<!-- Custom HTML -->
{% block content %}
{% include_block page.body %}
{% endblock %}
</div><!-- /.blog-post -->
{% endblock %}
{% block extra_js %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js"></script>
<script type="text/javascript">
// Custom JavaScript
</script>
{% endblock extra_js %}
This works great, thus extra css/js is indeed inserted where it belongs.
The problem arise if I need to use streamfield where one of its block templates need custom css/js. In this case custom resources are inserted along with the block, but not in the specified locations in the base.html.
For instance if extra_js from the page.html in the example above has been added to the block template instead, then select2 would complain about jquery not being present and it would be totally right, because it's inserted with the block, but not as intended after the Core JS libraries.
Loading jquery twice leads to other issues: https://stackoverflow.com/a/25782679/2146346
Other option is to load all block dependencies into the page, but it would fill pages with redundant resources as not every block from the streamfield might be used on the page.
Are there other options?
UPDATE: here’s a much better way that uses JavaScript to only load libraries once: https://github.com/FlipperPA/wagtailcodeblock/blob/main/wagtailcodeblock/templates/wagtailcodeblock/code_block.html#L6
I haven't come up with a way I like of doing this yet. The tools for doing this on the Wagtail editor side are nice. However, here's what I do for WagtailCodeBlock:
{% load static wagtailcodeblock_tags %}
{% spaceless %}
{# This is ugly, as it'll inject this code for each block, but browsers are smart enough to not load each time. #}
<script src="{% static 'wagtailcodeblock/js/prism.min.js' %}" type='text/javascript'></script>
<link href="{% static 'wagtailcodeblock/css/prism.min.css' %}" rel="stylesheet">
{% load_prism_theme %}
{% for key, val in self.items %}
{% if key == "language" %}
<script>
language_class_name = 'language-{{ val }}';
</script>
{% endif %}
{% if key == "code" %}
<pre class="line-numbers">
<code id="target-element-current">{{ val }}</code>
</pre>
<script>
var block_num = (typeof block_num === 'undefined') ? 0 : block_num;
block_num++;
document.getElementById('target-element-current').className = language_class_name;
document.getElementById('target-element-current').id = 'target-element-' + block_num;
</script>
{% endif %}
{% endfor %}
{% endspaceless %}
In this example, I load the JS/CSS assets in each, and let the browser settle it out. It also assumed jQuery is loaded at the parent level. However, it is also possible to use the JavaScript context to ensure things are only loaded once, which is my next step. For now, it isn't pretty but it works.
On the Wagtail editor side, there's the #property media. I wish there was something analogous on the rendered side:
class CodeBlock(StructBlock):
"""
Code Highlighting Block
"""
WCB_LANGUAGES = get_language_choices()
off_languages = ['html', 'mathml', 'svg', 'xml']
language = ChoiceBlock(choices=WCB_LANGUAGES, help_text=_('Coding language'), label=_('Language'))
code = TextBlock(label=_('Code'))
#property
def media(self):
theme = get_theme()
prism_version = get_prism_version()
if theme:
prism_theme = '-{}'.format(theme)
else:
prism_theme = ""
js_list = [
"https://cdnjs.cloudflare.com/ajax/libs/prism/{}/prism.min.js".format(
prism_version,
),
]
for lang_code, lang_name in self.WCB_LANGUAGES:
# Review: https://github.com/PrismJS/prism/blob/gh-pages/prism.js#L602
if lang_code not in self.off_languages:
js_list.append(
"https://cdnjs.cloudflare.com/ajax/libs/prism/{}/components/prism-{}.min.js".format(
prism_version,
lang_code,
)
)
return Media(
js=js_list,
css={
'all': [
"https://cdnjs.cloudflare.com/ajax/libs/prism/{}/themes/prism{}.min.css".format(
prism_version, prism_theme
),
]
}
)
class Meta:
icon = 'code'
template = 'wagtailcodeblock/code_block.html'
form_classname = 'code-block struct-block'
form_template = 'wagtailcodeblock/code_block_form.html'
I hope this gives you some ideas, and I'm all ears if you come up with a better way. Good luck.
Could you create another js block that you only add into the streamfield block template? So in base.html you'll have extra_js block as well as streamblock_js. You can have your jquery in extra_js and the extra dependency for the streamblock in streamblock_js. And if you have multiple custom css/js per streamblock on one page, you could add as many extra blocks in the base.html template to load all the dependencies. I'm not sure if this will work, but that's my idea.

Shopify variant swatches or radio buttons instead of dropdowns in Slate

Shopify's tutorial for color swatches isn't supported yet for Slate,
and the select callback referenced no longer exists in the code base. Is it possible to modify this tutorial to work on Slate themes to create radio buttons or swatches instead of a dropdown for selecting variants on the product template?
Yes. I was able to get this tutorial to work by modifying the code slightly. This workaround is only going to be relevant until the shopify tutorial is updated to correspond to Slate.
Follow the tutorial as per the directions.
When you get to the step "Locate your selectCallback function",
you will notice there is no selectCallback function in Slate. Yikes!
Instead find "_onSelectChange" in theme.js and add the code there.
This is the final function with the swatches code added:
/**
* Event handler for when a variant input changes.
*/
_onSelectChange: function() {
var variant = this._getVariantFromOptions();
this.$container.trigger({
type: 'variantChange',
variant: variant
});
if (!variant) {
return;
}
// BEGIN SWATCHES
var selector = this.originalSelectorId;
if (variant) {
var form = $(selector).closest('form');
for (var i=0,length=variant.options.length; i<length; i++) {
var radioButton = form.find('.swatch[data-option-index="' + i + '"] :radio[value="' + variant.options[i] +'"]');
if (radioButton.size()) {
radioButton.get(0).checked = true;
}
}
}
// END SWATCHES
this._updateMasterSelect(variant);
this._updateImages(variant);
this._updatePrice(variant);
this.currentVariant = variant;
if (this.enableHistoryState) {
this._updateHistoryState(variant);
}
},
Then, once you've completed the tutorial, you will notice it's still not working. This is because the code you add to theme.liquid uses a class that is no longer on your variant Selects.
On product.liquid (this is a Section on most Slate themes) Add the class "single-option-selector" to your selects, like so:
{% unless product.has_only_default_variant %}
{% for option in product.options_with_values %}
<div class="selector-wrapper js">
<label for="SingleOptionSelector-{{ forloop.index0 }}">
{{ option.name }}
</label>
<select
id="SingleOptionSelector-{{ forloop.index0 }}"
class="single-option-selector"
data-single-option-selector
data-index="option{{ option.position }}">
{% for value in option.values %}
<option value="{{ value | escape }}"
{% if option.selected_value == value %}selected="selected"{% endif %}>
{{ value }}
</option>
{% endfor %}
</select>
</div>
{% endfor %}
{% endunless %}
Now, the tutorial should work as it's supposed to. I hope this helps someone out!

Pelican - add image to summary

I'm using pelican to create a website. I'm trying to add an image to the summary so that the summary always starts with an image.
I tried adding the image to the summary in the metadata (using markdown) but it only shows up on the index page and not on the other pages (in the example below the image does not show in the Posts page). I also have to add the image in the same line as the text which sometimes renders in a weird way (some text is to the side of the image depending on the image size).
Here is an example of the metadata:
Title: this is my title
Slug: slug
Date: 2017-05-04 23:00
Category: Posts
Tags: pelican
Author: Eyal
Summary: ![figure 1](images/fig1.png) and this is my post summary
I also tried to use the summary plugin but that but that did not work at all.
What is the easiest way to add an image to the summary? I was hoping to avoid modifying the html code if possible.
Add the image as a field metadata in your article, say it "Cover", like this:
Title: this is my title
Slug: slug
Date: 2017-05-04 23:00
Category: Posts
Tags: pelican
Author: Eyal
Cover: images/fig1.png
Summary: and this is my post summary
So you can use it in your template in this way.
{% if article.cover %}<img src="{{ article.cover }}" alt="">{% endif %} {{ article.summary }}
This line looks for Cover key in the metadata, and if there is one, create the img tag. If is not, then simply pass.
Ad it there where article.summary already is used. I use pelican-theme alchemy (that uses bootstrap) and article.summary is in index.html. I extended it as follows:
<div class="col-sm-8">
<h4 class="title">{{ article.title }}</h4>
<div class="content">
{{ article.summary|striptags }}
{% if article.cover %}
<div class="container"><div class="col-md-6" style="padding-left: 0px; padding-right: 0px;">
<img src="{{ article.cover }}" class="img-fluid">
</div></div>
{% endif %}
</div>
</div>
This works for me with the pictures in the images-folder.
But I have an other problem: the posts do not find the pictures in the same images-folder :-(
For those using the AboutWilson template in Pelican I have managed to make it work as well by adding the following code in the index.html file (in the template folder)
{% if article.cover %}
Cover:
<span>
<img src="{{ article.cover }}" alt="">
</span>
{% endif %}

Wrap Phalcon flash messages in HTML element

Is there a possibility to wrap flash messages in an element? I want to have no html element at all when there are no messages and have an extra div containing all messages if there is any message.
It would be enough if I could at least get information whether there are any flash messages and then code it myself, but it seems to me that neither Phalcon\Flash\Direct nor Phalcon\Flash\Session allow you to access current message count or wrap messages in your own html element.
Just configure your flash service to just output the message:
$this->flash->setAutomaticHtml(false);
Also, when outputting a message, it's automatically echoed.
If you want to just return a string without echoing it to the output buffer use:
$this->flash->setImplicitFlush(false);
These methods aren't in the main documentation page, but you should always look at the class reference too, you might find very usefull information there :)
EDIT
To return only messages you use setAutomaticHtml to false, setImplicitFlush has nothing to do with it. Also to know if a message exists use something like this:
$this->flashSession->has('error');
I have ended with following code. I basically had to generate output myself.
<?php
$messages = $this->flashSession->getMessages();
if ( count($messages) > 0) {
?>
<div class="basic-bg">
<div class="main-column">
<div class="flash-messages">
<?php
foreach ($messages as $messageType => $messageArray) {
foreach ($messageArray as $message) {
echo "<div class=\"flash-$messageType\">$message</div>";
}
}
?>
</div>
</div>
</div>
<?php } ?>
I know this is an old thread, but how about implementing an extended class to make sure your message string is still correctly escaped?
This is the class I've used to implement Bootstrap 3 dismissable messages:
<?php
namespace Ext;
/**
* Extension to Phalcon Framework to implement Bootstrap 3 dismissable messages.
* Pass mappings of phalcon to bootstrap classes to construct
* #link https://docs.phalconphp.com/uk/latest/reference/flash.html Phalcon flash docs
* #author Kevin Andrews <kevin#zvps.uk>
*/
class FlashBootstrap extends \Phalcon\Flash\Session
{
/**
* Correctly escapes the message while building a Bootstrap 3
* compatible dismissable message with surrounding html.
* #param string $type
* #param string $message
* #return void
*/
public function message($type, $message)
{
$bootstrapCssClass = $this->_cssClasses[$type];
$errorType = ucfirst($type);
$bootstrapMessage = "<div class=\"alert alert-{$bootstrapCssClass} alert-dismissible\" role=\"alert\"><button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-label=\"Close\"><span aria-hidden=\"true\">×</span></button><strong>{$errorType}:</strong> {$this->getEscaperService()->escapeHtml($message)}</div>";
parent::message($type, $bootstrapMessage);
}
}
Also for completeness the initialisation for DI:
<?php
$di->set('flash', function() {
$bootstrapFlash = new Ext\FlashBootstrap(array(
'error' => 'alert alert-danger alert-dismissible',
'success' => 'alert alert-success alert-dismissible',
'notice' => 'alert alert-info alert-dismissible',
'warning' => 'alert alert-dismissible',
));
$bootstrapFlash->setAutoescape(false);
$bootstrapFlash->setAutomaticHtml(false);
return $bootstrapFlash;
});
This also has the advantage that the ->success() ->error() ->notice() and ->warning() helper methods will all go through this code and produce nicely formatted messages wrapped in the desired HTML.
{% if flash.has('notice')==true OR flash.has('success') %}
{% for notif in flash.getMessages('success') %}
<div class="notif_global success">
<div class="notif_global-title">Успешно</div>
<div class="notif_global-content">{{ notif }}</div>
<div class="notif_global-close ico_close"></div>
</div>
{% endfor %}
{% for notif in flash.getMessages('notice') %}
<div class="notif_global success">
<div class="notif_global-title">Сообщение</div>
<div class="notif_global-content">{{ notif }}</div>
<div class="notif_global-close ico_close"></div>
</div>
{% endfor %}
{% endif %}
{% if flash.has('warning')==true OR flash.has('error') %}
{% for notif in flash.getMessages('warning') %}
<div class="notif_global error">
<div class="notif_global-title">Предупреждение</div>
<div class="notif_global-content">{{ notif }}</div>
<div class="notif_global-close ico_close"></div>
</div>
{% endfor %}
{% for notif in flash.getMessages('error') %}
<div class="notif_global error">
<div class="notif_global-title">Ошибка</div>
<div class="notif_global-content">{{ notif }}</div>
<div class="notif_global-close ico_close"></div>
</div>
{% endfor %}
{% endif %}