Javascript / Django Design Pattern - javascript

I just have a question about how to achieve DRY with javascript that generates html on the fly. I have a list of elements that are loaded dynamically and populated by the django template a la
{{ tag.title }}
{% if request.user.is_authenticated %}
<a name="del-tag" data-id="{{ tag.id }}" class = "tag-x" title="Remove Tag" href="#">x</a>
{% endif %}
Now, I have some javascript that also loads new tags via ajax. Here's the relevant portion:
var newTag = "<span class = \"tag\">" + tagName + "<a name=\"del-tag\" data-id=\"" + tag_id + "\"" +
"class = \"tag-x\" title=\"Remove Tag\" href=\"#\">x</a></span>";
$('#tags').append(newTag);
Can I avoid duplicating HTML in the javascript?
Thanks.

jQuery Template could be used for this.

jquery(I'm assuming that's jquery that you are using) has a clone feature that can clone DOM elements. Given that you should be able to clone one of the html elements that already exist and change the value of the attributes, and then append it back to the DOM. I have not done this myself but it should work in theory.

Yes, you can do this. Have all tags generation functionality in a separate template. Then have some url which generates tags. Like this:
www.example.com/tags/?tags=tag1,tag2,tag3
this produces:
Then, when doing the AJAX call in your code do something like this:
$('div.tags').load('www.example.com/tags/?tags=tag1,tag2,tag3')
On the Django/template side you'd want to find a way how to include the result returned by the URL into the page template body. I'm not exactly sure what tools Django template engine provides, but on the first view it looks like you could put this code into some view method and extend this view everywhere you need it, providing the template variable as following render(..., tags=self.generate_tags(args)), in template it would be just {{ tags }}.
Both /tags/?tags=... and regular page /page/calls could re-use the generate_tags() method then.
Hope it helps

Related

Using {% include 'includes/some.html' %} in django template

I have a template as under:-
<div class= "comment-form m-2">
{% include "includes/comment_reply_form.html" %}</div>
If the user is authenticated then the html shows the form. However if the user is not logged in I want to show a Login button. I am handling the same by the following javascript.
$(".comment-reply-btn").click(function(event){
event.preventDefault();
if (user_is_authenticated === false) {
$(".comment-form").html('{% include "includes/reply.html" %}');
$(this).parent().next(".comment-reply").fadeToggle();
}
else {
$(this).parent().next(".comment-reply").fadeToggle();
}
});
But, instead of including the html in from reply.html, it is showing {% include "includes/reply.html" %} in the webpage. There is no problem with the javascript and if I add
<p> You need to Login </p>
in the following line. It works fine :-
$(".comment-form").html('{% include "includes/reply.html" %}');
But since I need more options in my reply.html I want to add it as includes. I have tried using the escape character "/" in front of { but it didn't help.
not familiar but try
<div class= "comment-form m-2">
<script>
document.write('{% include "includes/comment_reply_form.html" %}')
</script>
</div>
Instead of putting the value from include in your javascript function just put it in the html with with display = none for example
<div id="comment-reply-form-template">
{% include "includes/comment_reply_form.html" %}
Then in your javascript you can always clone the already rendered form when you need to...
Or you could make a custom template tag that will print the html in javascript string style with a bunch of '' + '' + ''
or prehaps look into the new es6 template strings
https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/template_strings
I think would work like
`{% include "includes/comment_reply_form.html" %}`
using the ` character

Django, html tags not interpreted

I am loading a text from the DB of a django project to display it in the template.
In the text stored within the data base, I added some HTML tags but it seems like the browser cannot interprete this html tags.
Here is my template:
<div>
<!-- body_text = "<strong>Hello</strong> word" -->
{{ entry.body_text }}
</div>
And I got the raw text: <strong>Hello</strong> word instead of
<strong>Hello</strong> word
What I am doing wrong?
If you don't want your HTML to be escaped, use safe filter:
{{ entry.body_text|safe }}
django doc about safe filter.
You can also try this:
{% autoescape off %}
{{ your_html_content }}
{% endautoescape %}
From django docs for autoescape:
Controls the current auto-escaping behavior. This tag takes either
on or off as an argument and that determines whether auto-escaping is in effect inside the block. The block is closed with
an endautoescape ending tag.
When auto-escaping is in effect, all variable content has HTML
escaping applied to it before placing the result into the output (but
after any filters have been applied). This is equivalent to manually
applying the escape filter to each variable.
As pointed out in the other answer, you can also use safe filter which:
Marks a string as not requiring further HTML escaping prior to output.
When autoescaping is off, this filter has no effect.
See here: safe filter.
Read more about django template tags and filters: Django Built-in template tags and filters

Open link contents in django template

I have a django application and in one of the templates I have something similar to:
image
This code is called multiple times - for each memb there is an associated .svg image that can be accessed with this url. Of course at the moment, there is just a link on the word 'image' to a separate page with the .svg.
What I want is to have the .svg's loaded into the template page instead of a link out. What is the easiest/best way to do this?
I am relatively new to Python/Django but I understand the basic concepts as well as HTML/CSS, however, I have zero experience with JavaScript.
EDIT: The .svg's are not stored in the filesystem. There is a separate view (separate to the main one for the template I'm working on here) that goes a bit like this:
def svg_image(request, entry_nr):
svg_string = utils.DrawSVG.get_svg(entry_nr)
return HttpResponse(svg_string)
I then have the url, which is accessed in the HTML template code above:
url(r'^images/(?P<entry_nr>[0-9]+)/$', views.svg_image, name='svg_image')
{% load static %}
<p>
<img src="/location/images/{{memb.EntryNr}}" width="200"/>
</p>
While rendering the django template you need to pass the content_type
def myview(request):
svg_data = generate_some_svg_data()
return HttpResponse(svg_data, content_type="image/svg+xml")

template inside html mustache js

I'm using mustache to render portion of html. To do this , I'm using this javascript :
var template = $("#div_name").html();
..
..
$("#container").append(Mustace.render(template,some_object));
As the <div id="div_name"></div> still remain inside the html , I use it only to get a template i was wondering : is it convenient to keep templated div html be inside the html or is better to load it e.g. with partials through ajax ?
Thanks in advance.
You can also keep templates inside script elements like so:
<script type="application/mustache" id="div_name">
//Mustache template code here
</script>
And fetch the template code from there using $("#div_name").html(). It won't be shown on the page and the script tag is not executed because of the invalid type.

Append Django template tag with Jquery

I want to build a menu where I can set one link highlighted using the {% block %} tag. I have something like this in my Javascript:
<loop>
$('#a-div').append('{% block ' + variable + ' %} <a href...</a> {% endblock %}')
<endloop>
In the source, this is displayed as "{% block Home %}"
How can I make JQuery not append this as a string but as a template tag?
You can't. At least not without making an AJAX request to a Django template. In your case, it would be slow and make unnecessary extra requests. It's just not worth it. You can insert snippets from Django templates via jQuery by using, for example, the jQuery load function. But you can't replace a specific {% block %} tag, because by the time jQuery runs, the template has already been processed (and references to block tags removed). But this is not a situation where you should be doing that in any case.
Why don't you rather highlight the menu with a CSS class? Here is my usual solution to this problem:
Create a file called base_extras.py in one of your templatetags folders. If you don't have one, create one in an appropriate folder.
Inside base_extras.py, paste this code:
from django import template
from django.core.urlresolvers import reverse
register = template.Library()
#register.simple_tag
def navactive(request, urls):
if request.path in ( reverse(url) for url in urls.split() ):
return "active"
return ""
Now, in your template, on your menus in your base template, do something like this:
<ul class="menu">
<li class="home {% navactive request 'home' %}">Home</li>
<li class="contact {% navactive request 'contact' %}">Contact</li>
<li class="signup {% navactive request 'signup' %}">Sign up</li>
</ul>
This will make that the menu where your URL currently is has the active class. Then, in your CSS, just add a special class for a menu item with active to look slightly different than the other menus.
ul.menu li.active {background: red; color: white;}
And if you happen to need to change the active menu with jQuery, you can just remove the active class on all menus, and add it to the newly selected menus:
$('ul.menu li').removeClass('active').find('.home').addClass('active'); // for example
You can't do that like that. The Django template tags are processed on the server side, before the page is even sent to the browser. Javascript (including jQuery) is, on the other hand, invoked in the browser, after the page has been received from the server.
What you can do is prerender the content of {% block %} tag to JS variable and use it in jQuery code:
var blockContent = "{% block Home %} ... {% endblock %}";
// ...
$("#a-div").append(blockContent);
If you need more than one block to choose from (as you seem to indicate in the code sample you've provided), you could resort to an array of prerendered blocks.
Your best bet is to create a proxy view that makes what is currently your AJAX request, processes the results like the javascript would, and then returns whatever you're trying to get from the Django templating system.
Then, instead of making the AJAX call you're currently making, you call your own view instead. Django does the processing in the view like it should, you get fine-grained control over what's returned to your javascript, and it's still only one (client-side) server call.

Categories

Resources