Django: Variables inside static tag - django

The question here seems to be very similar to mine; however, I tried what was suggested there but it did not work in my case so perhaps my question is different after all.
In my html file (in the <script></script> for the Javascript section), I have:
var snd = new Audio("{% static 'updateMap/cual_es_su_nombre.mp3' %}");
snd.play();
which plays the mp3 just fine; however, I would like to be able to replace the file name: cual_es_su_nombre.mp3 with a variable. I am getting the file name(s) from the server.
So, the first thing that I do is to load the file names into a Javascript array:
var all_file_names = new Array();
{% for item in all_file_names_from_server %}
all_file_names.push("{{ item |safe }}");
{% endfor %}
Then, ultimately, I would like to be able to do this for example:
var snd = new Audio("{% static 'updateMap/'|add:all_file_names[0] %}");
snd.play();
However, that does not work...

The Django template engine will have completely finished rendering the page before passing it to the browser. You can use it to write Javascript, but you can't access it from Javascript or in ways that depend on Javascript data structures. I think your best bet would be to build an array of the resolved static URLs rather than just an array of the filenames (possibly instead of that array if you don't need both). Something like:
var all_file_names = new Array();
{% for item in all_file_names_from_server %}
all_file_names.push("{{ item |safe }}");
all_file_uris.push("{% static 'updateMap/'|add:item|safe %}");
{% endfor %}
Then:
var snd = new Audio(all_file_uris[0]);
snd.play();

Related

Offline context with Wagtail Page data (Django-Compressor)

I've got Wagtail set up with Django-Compressor (COMPRESS OFFLINE = True) which all works except for one template.
This template uses the Disqus plugin which requires:
An absolute page url
A unique page identifier
In my template I have included the following:
{% compress js inline %}
// My JS Code
this.page.url = "{{ page.full_url }}";
this.page.identifier = {{ page.id }};
{% endcompress %
So when accessing the page I get the error You have offline compression enabled but key "ARANDOMKEYGOESHERE" is missing from offline manifest. As per the Django-Compressor docs:
If you use any variables inside the {% compress %} blocks, make sure to list all values you require in COMPRESS_OFFLINE_CONTEXT
How would I go about adding the Page instance to the context in my settings? I thought of something like (pseudo-code):
COMPRESS_OFFLINE_CONTEXT = { 'page': request.get('page') }

django, secondary data in subfolders

I am working on an informational site. I am attempting to access files in a subdirectory using data from the django db.
Ex: if the record.id = 1 and the file is desc.txt, I want to grab /1/desc.txt
I currently have two items that I'm trying to access this way. The image file will work if I hard code the location, but I haven't been able to get it to work from the record data. The other one, I'm trying to load a description file into a div using jQuery and .html(), and can't get it to work at all.
The relevant section of code:
{% if aRecord %}
{% load static from staticfiles %}
<h1>{{ aRecord.Name }}</h1>
<br/>
Born: {{aRecord.Birth}}<br/>
Died: {{aRecord.Death}}<br/>
<div id="descArea"><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/></div>
<script>
descfile = 'Authors/1/desc.txt';
$('#descArea').text(descfile);
$.get("{% static 'Authors/1/desc.txt' %}", function(data) {
$('#descArea').html(data);
});
</script>
<br/>
{% else %}
Requested author not found.
{% endif %}
This is the hard-coded version that works, but I need it to work from the aRecord data. The 1 in both cases should come from the record id, and the image filename in the img tag should as well.
It sounds like this is really a question about how to produce a file path from dynamic data. Is that the case? If so, you will probably need to use string substitution.
In order to produce a string like '/1/desc.txt' where the 1 is given by a record id, you could do something like this:
path = '/{}/desc.txt'.format(record.id).

Capture and append in Twig

What I need is to append text blocks to the same name in any template and finally print its value.
What I have so far.
In child template:
{% set tmp %}
...some text...
{% endset %}
{% set capture = capture|default([])|merge([tmp]) %}
In parent (main layout):
{{ capture|default([])|join|raw }}
{# it works in the same template but not in parent #}
I know it is ugly but still would be happy if it worked.
Ideally I'd like to make an extension to work like this:
{% capture %}
...some text...
{% endcapture %}
{# to capture #}
{% capture() %}
{# to print #}
but documentation that I've seen (http://twig.sensiolabs.org/doc/advanced.html) does not help.
I don't know what type of extension should I choose, where actual data manipulations are made, how I access and append data.
What existing extension could I use as a base?
Couldn't access even Twig global variable set in sf config.
So created 2 Twig functions: one to append content, another to get what is buffered.
Using twig extension class property as "global var" because container params turned out to be locked.
Usage:
set content to local var
append local var to global var
get and print raw global var content

Replace jquery-templ tag

Is there a way to replace the main tag on jquery-tmpl ?
Example:
var data = {Name: 'Pele', Languages: ["Portuguese","English","Spanish"]};
So on a script tag we define the following template
Name: ${Name}
{{each Languages}}
I speak $value
{{/each}}
What I wanted to change is ...
Istead of using {{each}} I'd use something like $$each$$
Instead of ${Name} I'd use something like $#Name$
You may be asking yourself why I wanna do this.
The main reason is when I because on the project we're working on uses Django and when we put code like {{each}} (even on script tag with type set to text/html) Django view engine think it's a server tag and tries to render it like if it were a server side tag.
Update:
What I'm looking for is a way to Set a Delimeter on jQuery-tmpl like the one that is avaiable on Mustache.js
http://mustache.github.com/mustache.5.html (look for Set Delimiter)
Thanks.
Sure, if you want a literal { in your HTML, use templatetag with openblock.
{% templatetag openblock %}
If you want a literal }, use closeblock:
{% templatetag closeblock %}
So if you want {{each}} in your HTML, use:
{% templatetag openblock %}{% templatetag openblock %}each{% templatetag closeblock %}{% templatetag closeblock %}
A different approach would be to define the template in a js file which is not processed by django as a template.
If that is not possible another alternative to Dominic's approach would be to define variables for '{{' and '}}' maybe jqtmpl_open and jqtmpl_close accordingly and use them in template like this:
{{ jqtmpl_open }}each Languages{{ jqtmpl_close }}
This would be more readable in the template.
Changing a delimiter for jquery-tmpl is complicated. By looking at the code it seems that {{ is hard coded within some regular expressions there.
var oldManip = jQuery.fn.domManip, tmplItmAtt = "_tmplitem", htmlExpr = /^[^<]* (<[\w\W]+>)[^>]*$|\{\{\! /,
newTmplItems = {}, wrappedItems = {}, appendToTmplItems, topTmplItem = { key: 0, data: {} }, itemKey = 0, cloneIndex = 0, stack = [];
The only solution would be to fork the jquery-tmpl for your project and change these hard coded regular expressions to accommodate your needs.
This question has already been asked here jquery template tags conflict with Django template! but I thought I would add from my experience.
In a nutshell, I've added this custom "raw" template tag to my jquery-tmpl/django projects: http://www.holovaty.com/writing/django-two-phased-rendering/

Django: Is there a better way to bold the current page link

I have a base.html template that contains a list of links.
Example:
<div id="sidebar1">
<ul>
<li>Index</li>
<li>Stuff</li>
<li>About Me</li>
<li>Contact Me</li>
</div>
Then I have in my views.py a definition for each of index.html, stuff.html, about.html and contact.html. Each of those templates simply derive from a base.html template and set their own respective titles and contents.
My question is about the above /stuff I have a class="current".
I'd like to make the current page that I'm on have that class attribute.
I could set a different variable in each view like current_page="about" and then do a compare in the template with {% ifequal %} in each class element of each link , but that seems like duplicating work (because of the extra view variable).
Is there a better way? Maybe if there is a way to get the view function name that the template was filled from automatically I would not need to set the extra variable? Also it does seem like a lot of ifequals.
Here's an elegant way to do this, which I copied from somewhere and I only wish I could remember where, so I could give them the credit. 8-)
I assign an id to each of my pages (or all the pages within a section) like this:
In index.html: <body id='section-intro'>...
In faq.html: <body id='section-faq'>...
In download.html: <body id='section-download'>...
And then an id for the corresponding links:
<li id='nav-intro'>Introduction</li>
<li id='nav-faq'>FAQ</li>
<li id='nav-download'>Download</li>
And the in the CSS I set a rule like this:
#section-intro #nav-intro,
#section-faq #nav-faq,
#section-download #nav-download {
font-weight: bold;
/* And whatever other styles the current link should have. */
}
So this works in a mostly declarative way to control the style of the link that the current page belongs in. You can see it in action here: http://entrian.com/source-search/
It's a very clean and simple system once you've set it up, because:
You don't need to mess about with template markup in your links
You don't end up using big ugly switch statements or if / else / else statements
Adding pages to a section Just Works [TM]
Changing the way things look only ever means changing the CSS, not the markup.
I'm not using Django, but this system works anywhere. In your case, where you "set their own respective titles and contents" you also need to set the body id, and there's no other Django markup required.
This idea extends easily to other situations as well, eg. "I want a download link in the sidebar on every page except the download pages themselves." You can do that in CSS like this:
#section-download #sidebar #download-link {
display: none;
}
rather than having to put conditional template markup in the sidebar HTML.
Haven't used Django, but I've dealt with the same issue in Kohana (PHP) and Rails.
What I do in Kohana:
<li><a href="/admin/dashboard" <?= (get_class($this) == 'Dashboard_Controller') ? "class=\"active\"" : NULL ?>>Dashboard</a></li>
<li><a href="/admin/campaigns" <?= (get_class($this) == 'Campaigns_Controller') ? "class=\"active\"" : NULL ?>>Campaigns</a></li>
<li><a href="/admin/lists" <?= (get_class($this) == 'Lists_Controller') ? "class=\"active\"" : NULL ?>>Lists</a></li>
What I do in Rails:
<li><a href="/main" <%= 'class="active"' if (controller.controller_name == 'main') %>>Overview</a></li>
<li><a href="/notifications" <%= 'class="active"' if (controller.controller_name == 'notifications') %>>Notifications</a></li>
<li><a href="/reports" <%= 'class="active"' if (controller.controller_name == 'reports') %>>Reports</a></li>
I see only a couple of ways of doing it, while avoiding repeated ifequals:
Javascript. Something along the lines of (jQuery):
var parts = window.location.pathname.split('/');
var page = parts[parts.length-1];
$('#sidebar1 a[href*=' + page + ']').addClass('current');
Change your views to contain a list of pages with their associated titles and URLs and create a {% for %} loop in your template, which will go through that list, and add a single {% ifequal %}.
Option 2 being the favorite from where I stand. If the logic for all of your pages is the same, and only the templates differ, you might consider using the FlatPages model for each of your pages. If the logic is different, and you need different models, you might consider using a menuing app of some sort. A shameless plug: I have a menuing app of my own
If you add the request context processor, it's pretty straightforward:
settings.py:
TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.request',
'django.contrib.auth.context_processors.auth' # admin app wants this too
)
Now you have access to the HttpRequest, which contains the request path. Highlighting the current page is a simple matter of checking if the path matches the link's destination, i.e., you're already there:
<li><a class="{% if request.path == '/' %}current{% endif %}" href="/">Index</a></li>
<li><a class="{% if request.path == '/stuff/' %}current{% endif %}" href="/stuff/">Stuff</a></li>
<li><a class="{% if request.path == '/about/' %}current{% endif %}" href="/about/">About Me</a></li>
<li><a class="{% if request.path == '/contact/' %}current{% endif %}" href="/contact/">Contact Me</a></li>