Complex comparisons on yesno filter? - python

I'm quite new at python/django.
I love django's templates, but there is one recurrent thing I cannot find
It's very common for me to have one conditional attribute on a (probably long) HTML tag. Most of the times that's an extra CSS class.
For example, let's say you have two links to switch languages, and you want to enable only one at a time. I find myself doing something like this:
{% get_language_info for LANGUAGE_CODE as l %}
<a href="/path/to/switch/to/spanish"
class="{% ifequal l.code "es" %} disable {% endifequal %}">
<img src="/spanish/flag/url" alt="Spanish">
</a>
<a href="/path/to/switch/to/english"
class="{% ifequal l.code "en" %} disable {% endifequal %}">
<img src="/english/flag/url" alt="English">
</a>
Other examples may be while rendering a list of items and checking for the "selected" one, etc.
On other languages I did this with a ternary operator, but I know that's considered "evil" on the python/django world :-)
I wonder if there's a way to leverage from the "yesno" filter. I've tried to do something like:
{{l.code=="es"|yesno:"disabled,"}}
But I couldn't get it to work... am I missing something?
Thanks in advance.

The problem is simply with your syntax in the code you posted:
{{l.code=="es"|yesno:"disabled,"}}
It's actually processed like:
{{ l.code=={{"es"|yesno:"disabled,"}} }}
(Note: that code doesn't work, it's just meant to illustrate how Django reads it)
What you want is a custom template tag that works like the if templatetag but returns like the yesno filter. You could search around on something like djangosnippets.com; maybe someone has already done the work for you. Otherwise, I'd suggest looking at the Django source code for those two and try to merge them into your own templatetag.

Or you could use jQuery/javascript to set the class:
http://api.jquery.com/attr/
something like this - not tested!
{% get_language_info for LANGUAGE_CODE as l %}
<script>
{% if l.code='es' %}
$('.english').attr('class','disable');
{% else %}
$('.english').attr('class','disable');
{% endif %}
</script>
<a href="/path/to/switch/to/spanish"
id="spanish" class='enable">
<img src="/spanish/flag/url" alt="Spanish" >
</a>
<a href="/path/to/switch/to/english"
id="english" class='enable">
<img src="/english/flag/url" alt="English">
</a>

Related

How do I assign an ID to a div using Django?

I'm using mezzanine, based on the django framework of Python and I'm trying to add a method for my blog posts. In the models.py I have added an incremental counter to be used as an id reference.
`
def get_new_id():
n = 100
i = 1
for i in range(n):
if i ==100:
break
print (i) ##just checking if it actually did what I asked
return i
This way I want to be able to show the newest post on my homepage without having to change it manually.
I'd probably still need to reverse the count so the last blogpost becomes number 1, but regardless, the issue is not that.
I understand the code might already be too little for what I want it to do but even this simple loop does not print i in the console, let alone place itself into the meta tag. I have added the reference to the method in the correct html page (or so I believe)
from blog_post_list.html
{% for blog_post in blog_posts.object_list %}
<div id="{{ blog_post.get_new_id }}" class="post-preview">
<a href="{{ blog_post.get_absolute_url }}">
<h2 class="post-title">
{{ blog_post.title }}
</h2>
</a>
{% if settings.BLOG_USE_FEATURED_IMAGE and blog_post.featured_image %}
{% block blog_post_list_post_featured_image %}
<a href="{{ blog_post.get_absolute_url }}">
<img class="img-thumbnail" src="{{ MEDIA_URL }}{% thumbnail blog_post.featured_image 730 474 %}">
I am wondering if it is just the method that is poorly written or if I'm doing something else wrong entirely. If I can assign an ID to every blogpost I could use it anywhere on my website which would be awesome. I'm a novice still so I appreciate any help that you can muster. For the moment, when I run this code, the ID is NOT implemented in the html, rather the entire method is just ignored. the id meta tag of the div remains empty. However ,from the same page (blog_post_list.html) other methods are invoked and do work properly in the same fashion so the link is there.
Thanks in advance
If you would like to give an id to each item rendered in the for loop, and you would like your id to increment you can simply add a Django for loop counter. In that case this would give a unique id for each item.
{% for blog_post in blog_posts.object_list %}
<div id="{{ forloop.counter }}" class="post-preview">
<a href="{{ blog_post.get_absolute_url }}">
<h2 class="post-title">
{{ blog_post.title }}
</h2>
</a>
{% if settings.BLOG_USE_FEATURED_IMAGE and blog_post.featured_image %}
{% block blog_post_list_post_featured_image %}
<a href="{{ blog_post.get_absolute_url }}">
<img class="img-thumbnail" src="{{ MEDIA_URL }}{% thumbnail blog_post.featured_image 730 474 %}">
...
Also, FYI: if there are 101 items in your queryset and you give id=1 for the first one and 101st one, id will not be unique. In HTML you should give unique ids to elements.

How to use django base extension along with angularjs ng-include?

I'm using ng-include like this
HTML
<div ng-app="myapp" ng-controller="myctrl" ng-include="/static/html/main.html"></div>
main.html
{% extends "app\base.html" %}
{% block content %}
<div ng-controller="myctrl1">
some content
</div>
{% endblock %}
base.html
<div ng-controller="myapp2">some content </div>
but this is not working, it is showing an errorr "SyntaxError: Unexpected token % at Object.parse (native)"
Please suggest me a better way to implement this.
I don't quite know what you're trying to do here. Angular templates and Django ones are quite different, even if they superficially share the same {{ var }} syntax. You can't inherit an Angular template from a Django one, or vice versa.
But there's no reason to want to do that anyway. Angular is already loading the template as a partial, which means it will be inserted into the div in base.html. There's no need for inheritance here at all.

Short conditional statement in django templates

I'm looking for short conditional statement in python/django templates, so I could write less and reuse more. Something like (tkey in disabled_rows) ? "disabled-row" : "".
Here's what I'm doing:
{% if tkey in disabled_rows %}
<tr class="disabled-row">
{% else %}
<tr>
{% endif %}
I also tried a custom template tag without success:
{{ (tkey in disabled_rows)|xif:'true,false' }}
xif implementation:
def xif(cond, args):
if cond:
return args.split(',')[0]
else:
return args.split(',')[1]
Extra points if you can explain why this is not implemented natively in python.
For the example you gave, this solution is short and simple:
<tr {% if tkey in disabled_rows %} class="disabled-row"{% endif %}>
Perhaps there is something else you're trying to achieve that would be better elucidated with a different example?

django philosophy: when to include templates and when to have code generate html?

When using Django templates, should I have some templates that act like "subroutines", so to speak, or should I generate HTML from within my code in these cases?
For example, I have a template with several lists of names, each of which I want to turn into a select. Should I have a template that renders the name_list variable into a select, and do something like this:
#in the view:
return {'name_list_1': name_list_1,
'name_list_2': name_list_2,
'name_list_3': name_list_3}
#in the template:
{% with name_list_1 as name_list %}
{% include "sub_name_list_select.html" %}
{% endwith %}
{% with name_list_2 as name_list %}
{% include "sub_name_list_select.html" %}
{% endwith %}
{% with name_list_3 as name_list %}
{% include "sub_name_list_select.html" %}
{% endwith %}
Or should I have a function in my code, name_list_to_select_html, which does the same job, and do this:
return {'name_list_1_html': name_list_to_select_html(name_list_1),
'name_list_2_html': name_list_to_select_html(name_list_2),
'name_list_3_html': name_list_to_select_html(name_list_3)}
#in the template:
{{ name_list_1_html|safe }}
{{ name_list_2_html|safe }}
{{ name_list_3_html|safe }}
Or are both of these wrong and I am getting the philosophy totally wrong?
Additional question: in terms of speed, is it slow to constantly include templates? Is that a bonus point for the in-code html generation?
Generally, HTML should only be generated in the templating system or directly related code. That keeps the view of the data completely separate from the business and functional logic. I feel that's a proper separation of concerns. Go with your first solution.
As for performance, Django should probably take around the same amount of time running either code. But it has built-in view and template fragment caching if you know those segments of code don't need to be regenerated on every request.

Could not parse the remainder in template

This is my DjangoTemplates/(mysite)/index.html. I'm trying to do some math in my index.html. I want to display the sum of the entire Stakes.amount_won for each user_name in the for loop. I think I have the syntax correct for the math, but it does not seem to work in the template.
The for loop should go through each user_name, and display their user_name as a link with the Amount Won: (total of amount_won for that user_name) below.
from django.db.models import Sum
<h1> Players </h1>
{% if latest_player_list %}
<ul>
{% for player in latest_player_list %}
<li>{{ player.user_name }} <br>Total Won: {{Stakes.objects.filter(player__user_name).aggregate(Sum('amount_won'))}}
</li>
{% endfor %}
</ul>
<br>
{% else %}
<p>No players are available.</p>
{% endif %}
<h3>New Player</h3>
Sorry if this is noobish. Thank you in advance for the help!
Although the import statement is not part of the template language, this isn't actually your problem - it will just show as text. The actual problem is your function call: Django doesn't allow calls with parentheses in templates. Only functions with no parameters are allowed. You need to do the lookup in the view and pass it in the context.
Of course, this is all clearly explained in the documentation.
The quick answer here is that you're trying to do too much in the template - for example, you can't use a Python import statement in a template at all, so I imagine that's just rendering as text. What you'd generally want here is to do the query logic in your view class, then pass the data to the template for rendering.

Categories

Resources