How to remove line break after a tag - django

I use Django template system to do code generation (not only for HTML). I'm somehow troubled by redundant line breaks in django templates.
Here is an example. The template is as below:
// something
{% for element in elements %}
Element: {{ element.name }},
{% endfor %}
// something else
The rendered output will be:
// something
Element: foo
Element: bar
// something else
Expected rendered output should be:
// something
Element: foo
Element: bar
// something else
After googled a bit, I know I can use {% spaceless %} to remove any white spaces in rendered output. It is quite useful for HTML, but will not work for other languages. My current solution is to add a special string after a tag and replace them with empty string in output.
Is there any better solution to remove line break after a tag?

For your production environment you might consider minifying your html to get that little bit more performance. For example using https://pypi.python.org/pypi/django-htmlmin.
If you are only interested in the esthetics, then the .strip function as noted by e-nouri is probably your best answer.

You can use .strip on your attributes to strip/trim.
// something
{% for element in elements %}
Element: {{ element.name.strip }},
{% endfor %}
// something else

The line breaks in code shouldn't matter, but you can avoid them when you put everything in one line, which doesn't look that good anymore:
{% for element in elements %}Element: {{ element.name.strip }},{% endfor %}

Related

what is difference between {{}} and {% %} in django templates

I am very new to django and working on it.. I visited a html file and dont know the difference between {{}} and {% %} in html files used
as here
{% load static %}
Thanks a lot
You can use
{% %} For sentences such as if and for or to call tags such as load, static, etc.
{{ }} To render variables in the template.
Read More about it at Django Docs
{% %} is for displaying code and {{}} is for displaying variables
There are three things in the template in Django
First is template variable and the second thing is template tag and third and last is template filter
so we write a template variable is {{}}
and write a template tag is {% %}
third and last is template filter {{variable |filter:arg}}
I'm new too for Django, so if i'm wrong, please someone correct me.
The difference between they are:
{{variable}} is used to use a variables. When the template encounters a variable, it evaluates that variable and replaces it with the result.
You also can use filters {{variable|filter}} like this:
{{name|length}} in this case you will use a variable "name" and return the length of that variable.
{%tag%} could use for loops or logic, or load external information into the template to be used by later variables. You can create block tags to help extend other html files parts. Also you can create custom tags.
A good place to see how to do it:
https://www.codementor.io/hiteshgarg14/creating-custom-template-tags-in-django-application-58wvmqm5f
Tags like loops and block, need to be closed.
{% %} for IF ELSE CONDITIONS and FOR LOOP etc
{{ }} for veriables that rendered from view function also used in FOR LOOP veriables like
`enter code here`
{% for obj in qs%}
{{ obj.veriable_name }}
{% endfor %}

Django template custom tag as boolean

This seems such a simple thing but I can't seem to get it to work for one, and two I can't seem to be getting a straight forward answer online on wether it can or can't be done.
I just want a simple tag that will work like so
{% if my_tag %}
render something
{% else %}
render something else
{% endif %}
now I don't care about filters or any other ways you might be able to do the same thing, I want it to look exactly like that, and work like described, I have a simple tag made that actually does return True or False as needed, and it's called if I call the tag like this
{% my_tag %}
however it does't get called if I add an if in front of the tag, is a feature this simple and logical not implemented?
Like the link to the potential duplicate states, you can use an assignment tag similar to the following that will return the current time:
#register.assignment_tag
def get_current_time(format_string):
return datetime.datetime.now().strftime(format_string)
Within your template you can then do what you are desiring to do:
{% if get_current_time %}
...show time
{% else %}
...don't show time
{% endif %}

Django put forloop.counter0 into custom tag argument list possible?

So I am using django-google-charts to generate bar chart. Here the chart is drawn in the "out" div.
However I want to generate more than one charts in one page, within different div, for example chart0 in "out0", chart1 in "out1", chart2 in "out2".
{% load googlecharts %}
<div id="out"></div>
{% googlecharts %}
{# some code here #}
{% graph "out" "out_data" "out_options" %}
{% endgooglecharts %}
So I tried to modify the {% graph "out" "out_data" "out_options" %}, my intention was
{% graph out|add:{{ forloop.counter0 }} "out_data" "out_options" %} so that graph output source will be replaced by out0, out1, out2, etc.
However the use of {{}} inside {{%%}} is not allowed. Plus the graph tag will take whatever at the first place as a string parameter as separated by comma.
Is it possible to solve the problem on the template side?
Thanks.
{% graph "out"|add:forloop.counter0 "out_data" "out_options" %}
no brackets inside {% %} and it should work
also: |add concatenates strings, you were concatenating a variable (out instead of "out")
the above code should now work as you expect :)
Finally I worked out fine using only the google chart tools Javasciprt API. It allows multiple charts on one page. Similar question here. The last answer is the solution.

Django templates - split string to array

I have a model field, which stores a list of URLs (yeah, I know, that's wrong way) as url1\nurl2\nurl3<...>. I need to split the field into an array in my template, so I created the custom filter:
#register.filter(name='split')
def split(value, arg):
return value.split(arg)
I use it this way:
{% with game.screenshots|split:"\n" as screens %}
{% for screen in screens %}
{{ screen }}<br>
{% endfor %}
{% endwith %}
but as I can see, split doesn't want to work: I get output like url1 url2 url3 (with linebreaks if I look at the source). Why?
Django intentionally leaves out many types of templatetags to discourage you from doing too much processing in the template. (Unfortunately, people usually just add these types of templatetags themselves.)
This is a perfect example of something that should be in your model not your template.
class Game(models.Model):
...
def screenshots_as_list(self):
return self.screenshots.split('\n')
Then, in your template, you just do:
{% for screen in game.screenshots_as_list %}
{{ screen }}<br>
{% endfor %}
Much more clear and much easier to work with.
Functionality already exists with linkebreaksbr:
{{ value|linebreaksbr }}
https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#linebreaksbr
Hm, I have partly solved this problem. I changed my filter to:
#register.filter(name='split')
def split(value, arg):
return value.split('\n')
Why it didn't work with the original code?
I wanted to split a list of words to get a word count, and it turns out there is a filter for that:
{{ value|wordcount }}
https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#wordcount
Apart from whether your original solution was the right approach, I guess the original code did not work because the meaning of the \n is not the same in Python code as it is in HTML: In Python code it means the escaped newline character, in HTML it is just the two separate characters \ and n.
So passing as input parameter \n from the HTML template to the Python code is equivalent to splitting on the Python string \\n: a literal \ followed by a n.

What's the best way to allow an infinite amount of foreign keys to the same model?

I'm making a forum with django right now, and I want it so that anyone can comment on anyone else's comment. Right now I have a foreign key in my 'Comment' model that points back to itself so I can get the parent comment easily from any comment.
In my theory this worked great, because from any comment I could get all of its child comments, and then just keep branching down from there to get every single child comment. However I'm having trouble actually implementing this when it comes to getting the data from the view to the template.
I want it to be possible to have an infinite number of child comments, because who knows how long a discussion will last and I don't want to arbitrarily limit it. The problem I'm having is would you get all of those comments from the view to the template without losing their relationship to their parent comment?
Currently this is what the psuedocode for my code looks like:
#the view
def comment_page(request, forum, comment_id):
#this is the main comment that all others will stem from
main_comment = Comment.objects.get(id=comment_id)
children_comments = main_comment.comment_set.all()
#the template
{% for comment in children_comments %}
<p class='comment'>{{comment}}</p>
{% endfor %}
Obviously I'm not even trying to get all the child comments here, it just gets child comments of the very first post. What I don't understand is how can I then go through each of these child comments and then get all of theirs, and keep doing that for each new comment?
It makes the most sense to do it in the view since I am able to use Django's QuerySet API in there, but I don't see how I would be able to pass all of the comments to the template without losing their relationship to their parent. The only idea I can think of is to go through all of the comments in the view and build up a string of html that I just pass and simply display in the template, but that seems like a horrible idea because it'd be dealing with template related stuff in the view.
You might want to look into using a MPTT such as django-mptt
this can be implemented by a custom filter with an inclusion_tag that includes itself but causes a lots of queries to your db:
#register.inclusion_tag('children.html')
def comments_tree(comment):
children = comment.comment_set.all()
return {'children': children}
# children.html
<ul>
{% for child in children %}
<li> {{ child }}</li>
{% if child.comment_set.count > 0 %}
{% comments_tree child %}
{% endif %}
{% endfor %}
</ul>
# your template
{% comments_tree comment %}
This older question is probably of interest:
How can I render a tree structure (recursive) using a django template?
Edit: to future readers, don't do this as the inner for loop's comment variable does not substitute the outer comment variable during the loop execution, leading to infinite recursion. /Edit
If you need a recursive tree structure in your HTML page (i.e. a bunch of nested <div> tags), you can write a recursive "comment" template.
Sample: (untested)
{# comment.html #}
<p class='comment'>{{ comment.text }}</p>
{% if comment.children %}
{% for comment in comment.children %}
{% include "comment.html" %}
{% endfor %}
{% endfor %}
The for loop binds the comment template variable to each child before including itself.
Performance note: Unless your comment sets are often short, this will probably be very slow. I recommend that you make your comments non-editable and cache the result!
Alternate solution: If you don't need the recursive HTML <div> tags, you can write a generator that performs a pre-order traversal of the structure and yields (depth, comment) pairs. This would likely be far more efficient in rendering speed.