Django and Mustache use the same syntax for template - javascript

I try to smuggle HTML template in the HTML for mustache.js, however
the django template engine remove all the placeholders that should be
output as-is to the front-end
The template is included in HTML in this way:
<script type="text/x-mustache-template" data-id="header_user_info">
<div id="header_user_info">
<div id="notification">0</div>
{{username}}
</div>
</script>
and I can get the HTML template by running $(el).html(), and generate
html by using Mustache.to_html(temp, data);
I could put all the template into another static file and serve from
CDN, but then it would be hard to track where the template belongs,
and at least one extra http request.

You can simply change the tags:
Mustache.tags = ['[[', ']]'];

You can use the {% templatetag %} templatetag to print out characters that would normally be processed by Django. For example:
{% templatetag openvariable %} variable {% templatetag closevariable %}
Results in the following in your HTML:
{{ variable }}
For a full list of arguments see: https://docs.djangoproject.com/en/dev/ref/templates/builtins/#templatetag

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 (python 2.7, HDR) use:
from django.template import Context, Template
import django
django.template.add_to_builtins('utilities.verbatim_template_tag')
html = Template(blob).render(Context(kwdict))
In your file (python 2.5) 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

Try to use django-mustachejs
{% load mustachejs %}
{% mustachejs "main" %}
Django-mustachejs will generate the following:
<script>Mustache.TEMPLATES=Mustache.TEMPLATES||{};Mustache.TEMPLATES['main']='<<Your template >>';</script>

I have the same issue, but using
{% templatetag openvariable %} variable {% templatetag closevariable %}
is too verbose for me. I've just added a very simple custom template tag:
#register.simple_tag
def mtag(tagContent):
return "{{%s}}" % tagContent
So that I can now write:
{% mtag "variable" %}

You can use the built-in mustache.js set delimiter tag to change the default tags that mustache uses.
i.e.
{{=<% %>=}}
now you can do this:
<% variable %>

I have the same issue, so most of the time my variables are part of a translatable string.
{% trans "The ball is {{ color }}" %}
You can use the trans templatetag even if you don't offer i18n.

Related

flask javascript can't print/log jinja2 request.form variable

Hi all I'm trying to get the value from flask and print it in javascript.
When I do print with a javascript string variable in my form it prints none.
var javascript_variable = "key_name";
// output is: request
console.log('request'+"{{request.form['"+javascript_variable+"']}}");
Also tried
// output is: request
console.log('request'+"{{request.form["+javascript_variable+"]}}");
however when I manually type the key name it works.
// output is: request key_information
console.log('request'+"{{request.form['key_name']}}");
Can someone please tell me what I'm doing wrong.
EDIT: I do not want to hardcode the keyname because the key_name is a changing dynamically
I'm trying to access that variable, so I can populate my select option/checkbox/radiobox option something like <option {% if request.form['key_name'] == "value" %} selected {% endif %} same for checkbox and radio box
In order to do that, you can use the flash statements inside the views in flask as follows,
#blueprint.route('/something.html', methods=['GET', 'POST'])
#login_required
def function():
try:
flash("Submission successful!")
except Exception as e:
traceback.print_exc()
return render_template('something.html')
In jinja, you can access the flash variable in the following way,
{% if get_flashed_messages() %}
{% for message in get_flashed_messages() %}
<script>window.alert("{{ message }}")</script>
{% endfor %}
{% endif %}

Conditionally insert a piece of Django template with HTML code into my template using Javascript

I am trying to create a template with Django to use with all the pages I have in my project. All the pages display similar tables which makes it easier but some of them require an extra check or two. So in writing this one-size-fits-all template, I would like to have this piece of code if it is one type of page:
{% if not package_check %}
<p style="color:red">Package not found, so script did not run. Install package and try again</p>
{% elif count|length %}
<!-- rest of html template -->
{% endif %}
Otherwise, I would like to have this piece of code:
{% if count|length %}
<!-- rest of html -->
{% endif | length %}
Since they are very similar I am wondering if it's possible (and how can I do it) to insert it into the HTML with Javascript when loading the page and make it test for the Django variables in the template tags.
Nothing understandable. Try to write clear.
You want to insert a new template or create a new html element from javascript
if you want include new template
you can do this
{% if not package_check %}
<p style="color:red">Package not found, so script did not run. Install package and try again</p>
{% elif count|length %}
<!-- rest of html template -->
{% include 'youranothertemplate.html' %}
{% endif %}
create new element from javascript
const newElement = document.createElement("h1")
newElement.innerText = "Hai"
document.getElementById("new").append(newElement)
<div id="new">
</div>

DjangoTemplate + Javascript - How to compare javascript variable with django multiple values

How to compare javascript variable "var1" with django multiple values. If a answer is ok, program should say ¡very good!
Django + Javascript:
<script>
var var1 = document.getElementById("userAnswer").value;
if (
{% for textEUS in question.textEUS.all %}
var1 == {{ textEUS }}
{% endfor %}
){
alert(¡Very good!);
}
</script>
only Django:
{% for textEUS in question.textEUS.all %}
{{ textEUS }}
{% endfor %}
only Javascript:
<script>
function tocorrect(){
var var1 = document.getElementById("userAnswer").value;
if (var1 == "answer"){
alert(¡Very good!);
}
}
</script>
What you're trying to do isn't possible the way you're trying to do it. This is the order of things:
Django renders a page using the django template language. This page might consist of HTML, javascript, and text really. All of the django tags, filters, variables have been assessed and processed at this point. For example:
{% for textEUS in question.textEUS.all %}
{{ textEUS }}
{% endfor %}
will have turned into a list of text.
The page rendered above is sent to your users browser
In the browser, the page is loaded, and javascript is executed, but at this point there are no more django template-tags etc.
The key point is:
You can't expect django template tags to 'run' at the sametime as your javascript. One happens on the backend, the other on the frontend.
You can however set a javascript variable using the django template language in the backend, and then use it in the front-end:
<script>
var var1 = document.getElementById("userAnswer").value;
// create a variable called textEusAll, this is completed in the backend
// before the page is sent to the user
var textEusAll = [
{% for textEUS in question.textEUS.all %}
"{{ textEUS }}"{% if not forloop.last %},{% endif %}
{% endfor %}
]
// use plain javascript for stuff happening in the front-end
if (textEusAll.includes(var1)) {
alert("¡Very good!");
}
</script>

Symfony2 - Change Page Content - Like Ajax

I am evaluating an ArrayCollection in my Template like this:
{% for article in articles %}
<li
{% if article.new %}
class="new"
{% endif %}
>{{ article.name|e }}</li>
{% endfor %}
Now I want to reload the articles ArrayCollection without reloading the whole page, like you would do in Ajax. Is it possible to reload it and let twig evaluate all the articles in a loop like the above?
I want to use twig to evaluate the content
It's possible, yes. You just need to make an ajax request to the action that'd return rendered collection.
This can be achieved by creating new action (recommended) or adding new paramenters in request that would tell twig which part to render or not (easier to do, harder to maintain).
Edit
Extending my answer because author requested me to.
Lets assume News controller in YourNs\YourBundle
Its contents should looks somewhat like this:
class NewsController extends Controller
{
/**
* #Route("/articles")
* #Template()
*/
public function listAction(){
$articles = $this->yourMethodToFindArticles();
return compact('articles');
}
}
Next thing to do is to render this action by adding YourNs/YourBundle/Resources/views/News/list.html.twig file and filling it up.
Once you have it done you'll need to add functionality to fire up ajax request to fetch refreshed collection of articles. FOSJsRouting might prove useful for that as well.
You can either add new action to controller
/**
* #Route("/_api/articles-list")
* #Template()
*/
public function apiListAction(){
$articles = $this->yourMethodToFindArticles();
return compact('articles');
}
And make its template render just your collection.
Or parametrize your first action and render template according to that:
{% if app.request.query.get('partial') %}
Template elements
{% endif %}
{% for article in articles %}
<li
{% if article.new %}
class="new"
{% endif %}
>{{ article.name|e }}</li>
{% endfor %}
{% if app.request.query.get('partial') %}
Other template elements
{% endif %}
Second solution is clearly inferior to the first one, especially once you start using esi tags, if you do that your code would look like this:
class NewsController extends Controller
{
/**
* #Route("/articles")
* #Template()
*/
public function listAction(){
return [];
}
/**
* #Route("/_api/articles-list")
* #Template()
*/
public function apiListAction(){
$articles = $this->yourMethodToFindArticles();
return compact('articles');
}
}
And listAction() template:
Template elements
{{ render_esi(url('yourns_yourbundle_news_apilist' }}
Other template elements
Note that the above snippets are just a simplified solution explaining trivial issue.
Edit2
Example of fetching that uses FOSJsRouting, js code with the api action:
var url = Routing.generate('yourns_yourbundle_news_apilist')
var fetchedCollection = $.get(url);
And example with parametrized template:
var url = Routing.generate('yourns_yourbundle_news_list', {'partial': 'true'})
var fetchedCollection = $.get(url);

Retrieving the URL in Django template language

In a Django template, how could I refer to the URL. I want to use it in static pages, to avoid having live links to the current page. Is there a way to do this with the Django template language or do I have to use JavaScript to do it?
I would like to do something like
{% if current_url == "/about/" %}
About
{% else %}
<a href='/about/'>About</a>
{% endif %}
I'm using it for a simple blog, so there are no views written for those pages.
I presume by your reference to 'static pages' you mean generic views. Internally, these use RequestContext, so you have access to the request object which is the current HttpRequest. So you can access the current URL with request.path.
{% if request.path == '/about/' %}
...
{% endif %}
Note that this if syntax is Django 1.2+ only - if you're using an older version, you have to do:
{% ifequal request.path '/about/' %}
...
{% endifequal %}
instead of current_url in your example above, you can substitute request.path (assuming you've got django.core.context_processors.request in play). And it'd have to be == not = :o)
I think you can accomplish this with simple template inheritance:
# base.html
{% block contactlink %}<a href='/contact/'>Contact</a>{% endblock %}
{% block aboutlink %}<a href='/about/'>About</a>{% endblock %}
...
# about.html
{% block aboutlink %}About{% endblock %}
# contact.html
{% block contactlink %}Contact{% endblock %}
Of course this only works if you have a separate template for each page, but I'm assuming you do since you said the pages are static. Knowing more about what views you are using (assuming generic view direct_to_template or similar) and your urls.py would help.

Categories