I want to use AngularJS with Django however they both use {{ }} as their template tags. Is there an easy way to change one of the two to use some other custom templating tag?
For Angular 1.0 you should use the $interpolateProvider apis to configure the interpolation symbols: http://docs.angularjs.org/api/ng.$interpolateProvider.
Something like this should do the trick:
myModule.config(function($interpolateProvider) {
$interpolateProvider.startSymbol('{[{');
$interpolateProvider.endSymbol('}]}');
});
Keep in mind two things:
mixing server-side and client-side templates is rarely a good idea and should be used with caution. The main issues are: maintainability (hard to read) and security (double interpolation could expose a new security vector - e.g. while escaping of serverside and clientside templating by themselves might be secure, their combination might not be).
if you start using third-party directives (components) that use {{ }} in their templates then your configuration will break them. (fix pending)
While there is nothing we can do about the first issue, except for warning people, we do need to address the second issue.
you can maybe try verbatim Django template tag
and use it like this :
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
{% verbatim %}
<div ng-app="">
<p>10 is {{ 5 + 5 }}</p>
</div>
{% endverbatim %}
If you did separate sections of page properly then you can easily use angularjs tags in "raw" tag scope.
In jinja2
{% raw %}
// here you can write angularjs template tags.
{% endraw %}
In Django template (above 1.5)
{% verbatim %}
// here you can write angularjs template tags.
{% endverbatim %}
We created a very simple filter in Django 'ng' that makes it easy to mix the two:
foo.html:
...
<div>
{{ django_context_var }}
{{ 'angularScopeVar' | ng }}
{{ 'angularScopeFunction()' | ng }}
</div>
...
The ng filter looks like this:
from django import template
from django.utils import safestring
register = template.Library()
#register.filter(name='ng')
def Angularify(value):
return safestring.mark_safe('{{%s}}' % value)
So I got some great help in the Angular IRC channel today. It turns out you can change Angular's template tags very easily. The necessary snippets below should be included after your angular include (the given example appears on their mailing lists and would use (()) as the new template tags, substitute for your own):
angular.markup('(())', function(text, textNode, parentElement){
if (parentElement[0].nodeName.toLowerCase() == 'script') return;
text = text.replace(/\(\(/g,'{{').replace(/\)\)/g, '}}');
textNode.text(text);
return angular.markup('{{}}').call(this, text, textNode, parentElement);
});
angular.attrMarkup('(())', function(value, name, element){
value = value.replace(/\(\(/g,'{{').replace(/\)\)/, '}}');
element[0].setAttribute(name, value);
return angular.attrMarkup('{{}}').call(this, value, name, element);
});
Also, I was pointed to an upcoming enhancement that will expose startSymbol and endSymbol properties that can be set to whatever tags you desire.
I vote against using double parentheses (()) as template tag. It may work well as long as no function call is involved but when tried the following
ng:disabled=(($invalidWidgets.visible()))
with Firefox (10.0.2) on Mac I got a terribly long error instead of the intended logic. <[]> went well for me, at least up until now.
Edit 2012-03-29:
Please note that $invalidWidgets is deprecated. However I'd still use another wrapper than double braces. For any angular version higher than 0.10.7 (I guess) you could change the wrapper a lot easier in your app / module definition:
angular.module('YourAppName', [], function ($interpolateProvider) {
$interpolateProvider.startSymbol('<[');
$interpolateProvider.endSymbol(']>');
});
API docs.
You could always use ng-bind instead of {{ }}
http://docs.angularjs.org/api/ng/directive/ngBind
<span ng-bind="name"></span>
I found the code below helpful. I found the code here: http://djangosnippets.org/snippets/2787/
"""
filename: angularjs.py
Usage:
{% ng Some.angular.scope.content %}
e.g.
{% load angularjs %}
<div ng-init="yourName = 'foobar'">
<p>{% ng yourName %}</p>
</div>
"""
from django import template
register = template.Library()
class AngularJS(template.Node):
def __init__(self, bits):
self.ng = bits
def render(self, ctx):
return "{{%s}}" % " ".join(self.ng[1:])
def do_angular(parser, token):
bits = token.split_contents()
return AngularJS(bits)
register.tag('ng', do_angular)
If you use django 1.5 and newer use:
{% verbatim %}
{{if dying}}Still alive.{{/if}}
{% endverbatim %}
If you are stuck with django 1.2 on appengine extend the django syntax with the verbatim template command like this ...
from django import template
register = template.Library()
class VerbatimNode(template.Node):
def __init__(self, text):
self.text = text
def render(self, context):
return self.text
#register.tag
def verbatim(parser, token):
text = []
while 1:
token = parser.tokens.pop(0)
if token.contents == 'endverbatim':
break
if token.token_type == template.TOKEN_VAR:
text.append('{{')
elif token.token_type == template.TOKEN_BLOCK:
text.append('{%')
text.append(token.contents)
if token.token_type == template.TOKEN_VAR:
text.append('}}')
elif token.token_type == template.TOKEN_BLOCK:
text.append('%}')
return VerbatimNode(''.join(text))
In your file use:
from google.appengine.ext.webapp import template
template.register_template_library('utilities.verbatim_template_tag')
Source:
http://bamboobig.blogspot.co.at/2011/09/notebook-using-jquery-templates-in.html
You can tell Django to output {{ and }}, as well as other reserved template strings by using the {% templatetag %} tag.
For instance, using {% templatetag openvariable %} would output {{.
I would stick with a solution that uses both django tags {{}} as well angularjs {{}} with a either a verbatim section or templatetag.
That is simply because you can change the way angularjs works (as mentioned) via the $interpolateProvider.startSymbol $interpolateProvider.endSymbol but if you start to use other angularjs components like the ui-bootstrap you will find that some of the templates are ALREADY built with standard angularjs tags {{ }}.
For example look at https://github.com/angular-ui/bootstrap/blob/master/template/dialog/message.html.
If you do any server-side interpolation, the only correct way to do this is with <>
$interpolateProvider.startSymbol('<{').endSymbol('}>');
Anything else is an XSS vector.
This is because any Angular delimiters which are not escaped by Django can be entered by the user into the interpolated string; if someone sets their username as "{{evil_code}}", Angular will happily run it. If you use a character than Django escapes, however, this won't happen.
How to add an emoji to a Hugo page variable? E.g. inside the title in the following code snippet:
date = "2016-11-20T12:00:00"
draft = false
tags = ["Fun"]
title = "Went sporting :heart:"
Hugo has two ways of handling Emojis.
Setting enableEmoji=true in your site config will handle emoji syntax like :heart: in your markdown content.
For titles etc. you must use the emojify template func, so in your template:
{{ .Title | emojify }}
I am building a setup that will contain a main site and a number of microsites. Each microsite is going to have a separate branding but use the same page types.
Given Wagtail already has a Site object which links to an appropriate Page tree, is there also built in functionality to configure the template loaders to choose an appropriate base.html or will I have to write a custom template loader?
Wagtail doesn't have any built-in functionality for this, as it doesn't make any assumptions about how your templates are put together. However, you could probably implement this yourself fairly easily using the wagtail.contrib.settings module, which provides the ability to attach custom properties to individual sites. For example, you could define a TemplateSettings model with a base_template field - your templates can then check this setting and dynamically extend the appropriate template, using something like:
{% load wagtailsettings_tags %}
{% get_settings %}
{% extends settings.my_app.TemplateSettings.base_template %}
I extended the above answer to provide an override of the {% extends ... %} tag to use a template_dir parameter.
myapp.models:
from wagtail.contrib.settings.models import BaseSetting, register_setting
#register_setting
class SiteSettings(BaseSetting):
"""Site settings for each microsite."""
# Database fields
template_dir = models.CharField(max_length=255,
help_text="Directory for base template.")
# Configuration
panels = ()
myapp.templatetags.local:
from django import template
from django.core.exceptions import ImproperlyConfigured
from django.template.loader_tags import ExtendsNode
from django.template.exceptions import TemplateSyntaxError
register = template.Library()
class SiteExtendsNode(ExtendsNode):
"""
An extends node that takes a site.
"""
def find_template(self, template_name, context):
try:
template_dir = \
context['settings']['cms']['SiteSettings'].template_dir
except KeyError:
raise ImproperlyConfigured(
"'settings' not in template context. "
"Did you forget the context_processor?"
)
return super().find_template('%s/%s' % (template_dir, template_name),
context)
#register.tag
def siteextends(parser, token):
"""
Inherit a parent template using the appropriate site.
"""
bits = token.split_contents()
if len(bits) != 2:
raise TemplateSyntaxError("'%s' takes one argument" % bits[0])
parent_name = parser.compile_filter(bits[1])
nodelist = parser.parse()
if nodelist.get_nodes_by_type(ExtendsNode):
raise TemplateSyntaxError(
"'%s' cannot appear more than once in the same template" % bits[0])
return SiteExtendsNode(nodelist, parent_name)
myproject.settings:
TEMPLATES = [
{
...
'OPTIONS': {
...
'builtins': ['myapp.templatetags.local'],
},
},
]
I'm using WTforms with Jinja2 and want to change my templates page title depending on whether I am creating a new instance of editing an existing form object.
This is what I wrote in the template:
{% block title %}{% if form.obj %}Edit{% else %}New{% endif %} Post{% endblock %}
What I expect to see:
if the form is filled out I expect to see "Edit Post" in the page title.
if the form is empty I expect to see "New Post" in the page title.
What I get: "New Post" in both instances.
Here is my PostHandler that is passing the form values.
def with_post(fun):
def decorate(self, post_id=None):
post = None
if post_id:
post = models.BlogPost.get_by_id(int(post_id))
if not post:
self.error(404)
return
fun(self, post)
return decorate
class PostHandler(BaseHandler):
def render_form(self, form):
self.render_to_response("edit.html", {'form': form})
#with_post
def get(self, post):
self.render_form(MyForm(obj=post))
#with_post
def post(self, post):
form = MyForm(formdata=self.request.POST, obj=post)
if post and form.validate():
form.populate_obj(post)
post.put()
post.publish()
self.render_to_response("published.html", {'post': post})
elif self.request.POST and form.validate():
post = models.BlogPost()
post.title = form.title.data
post.body = form.body.data
post.tags = form.tags.data
post.publish()
self.render_to_response("published.html", {'post': post})
else:
self.render_to_response('edit.html', {'form':form})
In short, all I'm trying to do is test whether the form is filled, and change my page title "New Post" or "Edit Post" accordingly.
While Form accepts a obj argument, it doesn't actually store it, it just uses that obj to fill in any blanks that formdata didn't provide. So when you ask Jinja2 {% if form.obj %} it's always going to be False, because there is never a obj property (unless you have a field that happens to be called obj of course).
If you're editing a post, you'll have an id to work with so you know which post to update in the database, so where are you currently storing that? Assuming you store it as a hidden field, you could just do:
{% if form.id.data == None %}Must be a New form {% endif %}
If you wanted to check if the entire form was empty, you could access the form.data dictionary, and make sure all the entries are None, although you need to be careful, because I know that FileField returns a u'None' instead of a real None, so you'd have to double check what Fields you care about.
I have this in the Google App Engine python code,
class ABC(db.Model):
StringA = db.StringProperty()
abcs = ABC.all()
template_values = {'abcs': abcs,}
path = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(path, template_values))
and this in the index.html,
<script type="text/javascript">
{% for abc in abcs %}
var id = "{{ abc.ID }}"; // needed the entity ID, the abc.ID doesn't show??
{% endfor %}
</script>
What was the right keyword to use for the entity ID, the abc.ID??
Thanks in advance.
{{abc.key.id}}, assuming you're using Django templates. The ID isn't a property of the object, it's a part of the object's Key; in a Django template (which is what you're using if you're using google.appengine.ext.webapp.template), this is the equivalent to abc.key().id() in Python code.
Note that not all entities have an ID at all; they could have a key name instead if you've set one.