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);
Related
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>
Hi I am building a simple blog using Python/Django. In my index.html file, I am trying to show archived posts when a button containing a month is clicked. At the moment, I am just trying to get the id of every post made in that month into a javascript array. For some reason though,it always returns true!
<script type="text/javascript">
function showPosts(month)
{
var posts_in_month=[];
{% for post in all_posts %}
var match = {{ post.pub_date.month }}
{% ifequal match month %}
posts_in_month.push({{ post.id }})
{% endifequal %}
{% endfor %}
}
</script>
I then go on to have a switch statement where I show the contents of the array depending on the month clicked. The code definitely works, when I call an alert(month) it shows up correctly, and when I call alert({{ post.pub_date.month }}) it shows up fine as well. These are usually not the same though, why is it always evaluating the ifequal to true?
You cannot create Javascript variable in python and use it as python's variable.
Replace the match with actual value:
{% ifequal post.pub_date.month month %}
posts_in_month.push({{ post.id }})
{% endifequal %}
I have a select box that calls a function on changes. The function finds the selected value from "Products" selectbox.
I want to throw that selected value to my views.py which after some operations return the list of data and Populates the Destination's selectbox.
I want to use ajax for this purpose. Please help.
My code looks like this:
<script type="text/javascript">
function select_value()
{
var e = document.getElementById("Product");
var prod = e.options[e.selectedIndex].text
console.log(prod)
}
</script>
This is what my selectbox look like:
<table>
<tr>
<td>
<select id="Product" onChange="select_value();">
{% for products in product_name_list %}
<option>{{products|safe}}</option>
{% endfor %}
</select>
</td>
<td>
<select id="dest">
{% for des in destinations_name_list %}
<option>{{des|safe}}</option>
{% endfor %}
</select>
</td>
</tr>
</table>
This is my views.py:
def selection_filter(request,prod):
destination_objs = Destination.objects.filter(product=prod)
destination_name = destination_objs.values_list('name')
destination_name_list = []
for iter_name in destination_name:
destination_name_list.append(iter_name[0].encode('utf-8'))
return render_to_response('temp/test.html',
{"destination_name_list" : destination_name_list},
)
I think the point you might be misunderstanding is that your Django template for your whole page will not be re-rendered "magically". In Django's standard model-view-template paradigm, the template is rendered just once, upon the initial request. The way you've written it, unless there's a default product selection, you're going to have an awkward empty <select> in the first render. But ignoring that...
For a problem like this, you need two views: one for rendering the whole page, and one for providing the Ajax response. There are two main options for the second view: 1) return JSON for interpretation/rendering by your script post-response or 2) return a fully rendered HTML fragment for direct insertion into your DOM. In this case, I'd just go for option 2.
I recommend looking into Jquery, as it makes Ajax and DOM manipulation super simple.
If you've got Jquery, it's as simple as adding to your script:
$.get('/destinations/' + prod)
.done(function (html) {
$(#dest).html(html);
});
(You can do the same thing without Jquery too, but it requires a bit more wrangling)
Your test.html file should contain:
{% for des in destinations_name_list %}
<option>{{des|safe}}</option>
{% endfor %}
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.
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.