Problem comparing keys in Appengine/Python - python

I'm trying to create a relationship between "tables" with Appengine/Python. Imagine I have a "table" for items, and a table for colors. I save the color of an item by saving the color key as an atribute of the item.
That's working well, but this particular piece of code is not working:
<select id="colorKey" name="colorKey">
{% for color in colors %}
<option value="{{ color.key }}"{% if color.key = item.colorKey %} selected="selected"{% endif %}>
{{ color.name }} - {{ item.colorKey }} - {{ color.key }}
</option>
{% endfor %}
</select>
Since the {{ item.colorKey }} and {{ color.key }} variables are actually the same chain of characters, I only can think in a problem with the types.
{{ item.colorKey }} is a string for sure. But maybe {{ color.key }} is not?

Indeed. color.key probably refers to an instance of the Key class. {% ifequal %} tries to compare a string with a Key object and the condition is never met.
Django automatically casts this object into a string when you're using {{ color.key }} but you have to provide {% if equal %} with an actual string.
You can declare a new property in your Color class that returns the key as string and then use it with {% if equal %}
class Color(db.Model):
...
#property
def keyasstring(self):
return str(self.key())
Then in your Django template:
{% ifequal color.keyasstring item.colorKey %}

{% if color.key = item.colorKey %}
One too few ==?

Django doesn't support arbitrary expressions in 'if' tags (or anything else for that matter). You need to use the 'ifequal' tag - see the docs for details.

Related

Pass arbitrary data from a FlaskForm object to the template

While building a small Flask based web app, I came across the need to pass arbitrary data from a Form Field object to the template where it's being rendered. However, I can't seem to find a way to do this.
The only place I think I could add such data was to the kwargs property of WTForms Field objects, but then I seem to have no way to access those properties from the template.
In case you're wondering what I'm trying to accomplish, I'm writing a template macro to ease form rendering, and I need to pass some extra data from the Form fields objects - mostly layout related, but which will not be HTML attributes for the fields themselves (which is what kwargs is designed for).
I found an answer here but it's not an answer per se but I comment.
Quoting Crast:
The description keyword argument of WTForms fields is allowed to be set at field construction, and is not inspected, just copied directly onto the field, and thus can be any value, not just a string, even a custom attribute. If you want to carry over your own metadata, you can simply use this to carry over any data you may want: TextField(..., description={'placeholder': foo', 'class': bar} (or even a custom class) then use this attribute in your template for any special metadata you want.
Yes, I know about separating content and presentation and the purpose of the description property isn't really intended for this kind of use, but it's the only way I found to pass data back to the template where I use a macro to render forms.
To access the passed data inside description from the template I did something like this:
{% macro render_create_form(form, form_title, enctype=None) %}
<h2>{{ form_title }}</h2>
<form action="" method="post"{% if enctype %} enctype="{{ enctype }}"{% endif %}>
{{ form.hidden_tag() }}
{% for field in form if not field.name == 'csrf_token' %}
{% set class_name = field.description.class %}
{% if field.type == "StringField" or field.type == "PasswordField" or field.type == "BooleanField" or field.type == "SelectField" %}
<div class="{{ class_name }}">{{ field.label }} {{ field }}</div>
{% elif field.type == "NumberField" %}
<div class="{{ class_name }}">{{ field.label }} {{ field(type='number', min=field.description.min, max=field.description.max, placeholder=field.description.placeholder) }}</div>
{% elif field.type == "HiddenField" %}
{{ field }}
{% elif field.type == "SubmitField" %}
<div class="{{ class_name }}">{{ field }}</div>
{% endif %}
{% endfor %}
</form>
{% endmacro %}

django concat string with comma in template

I am newbie in django. How can I concat string in a for loop in django template
{% for lead in project.leaders %}
{% if forloop.counter == 1 %}
{% lead_member = lead.0 %}
{% else %}
{% lead_member = ','.lead.0 %}
{% endif %}
{{ lead_member }}
{% endfor %}
Finally my lead_member should be test1,test2,test3....
what is happening now (my current code)
{% for lead in project.leaders %}
{{ lead.0}}
{% endfor %}
and the output is test1test2test3.... but i want to make same as test1,test2,test3....
Try this. it works
{% for lead in project.leaders %}
{{ lead.0 }}{% if not forloop.last %}, {% endif %}
{% endfor %}
There's no need to assign anything, nor do you need that type of complexity by using assignment tags. To keep your templating stupid-simple, you could always do this in your view, or even at the model level:
# don't step on the `join` built-in
from django.template.defaultfilters import join as join_filter
class Project(models.Model):
#property
def leaders(self):
return join_filter(self.objects.values_list('some_field', flat=True), ', ')
Then all you have to do in the template is:
{{ project.leaders }}
It's hard to understand your question, but I hope i did it. There is a number of related questions such as String-concatination,
How to concatenate in django
It's possible to create first string, concatinate it with comma and new string for every iteration. You are also able to make smth like ','.join(list_of_strings) on your server side before rendering. You can also join your list in templating by {{ list|join:", " }}.

How to use __repr__ method within django template?

For example, there is an object in a nested loop:
{% for fieldset in inline_admin_form %}
{% for line in fieldset %}
{% for field in line %}
{% if field.is_hidden %} {{ field.field }} {% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
{% endif %}
Now I want to check the class name and some information about field.field, so I use field.field.__repr__() to replace field.field.
However, the django template complains about it after the change:
Variables and attributes may not begin with underscores: 'field.field.__repr__'
Does anyone have idea about this? And is there any better way to debug for a variable in django template? (I tried {% debug %} but found it awful when I want to check a variable in a nested loop..)
{{ value|stringformat:'r' }}
uses the string % operator style formatting with the r format which uses repr()
You could easily write a template filter which allows you to do {{ var|asrepr }}. See the documentation, but it'll look something like this:
#register.filter
def asrepr(value):
return repr(value)

Determine empty template variable in Django

I'm not able to determine whether a variable is empty when used in the template.
I've iterated through the whole collection and in each I'm looking for a variable narrative_text.
I tested the empty variable by
{% ifnotequal narratives.narrative_text '' %}
I notice the control enters this block, but prints nothing/blank when the
{{ narratives.narrative_text }}
is encountered.
So, how do I precisely check if the variable is empty?
I read the docs and found out that invalid/empty template variables are replaced by ''.
The doc says that
the template system inserts the value of the TEMPLATE_STRING_IF_INVALID setting.
Do we have to explicitly enter that into the settings.py? I tried doing so but still I haven't been able to make it work.
c=Context({
"narratives_list":all_narratives,
"patient_name":care_seeker_name
})
all_narratives is returned by a pymongo database call.
{% for narratives in narratives_list %}
<tr>
<td class = "date_col">
7 Aug, 2012
</td>
{% ifnotequal narratives.narrative_text '' %}
<td>
<div class = "narrative">
( text narrative )
<b>
{{ narratives.about }}
</b>
<br><br>
{{ narratives.narrative_text }}
</div>
</td>
{% else %}
<td>
<div class="scans">
<div class="gallery">
<b> {{ narratives.about }}</b>
<br><br>
<a href="https://udhc1-nodejstest.rhcloud.com/my_image/{{ narratives.file_id }}">
<img src="https://udhc1-nodejstest.rhcloud.com/my_image/{{ narratives.file_id }}" width="72" height="72" alt="" />
</a>
</div>
</div>
</td>
{% endifnotequal %}
Pipe through length and do your test against that value.
{% if narratives.narrative_text|length > 0 %}
{{ narratives.narrative_text }}
{% else %}
None
{% endif %}
Just use {% if narratives.narrative_text %}, I think. It will use Python's implicit false, which applies for empty strings, empty arrays, empty dicts, None, False, 0 etc..
Just confirmed via my own code using django 2.1.3 and python 3.5 and 3.7 that the following works:
{% if narratives.narrative_text %}
# do something
{{ narratives.narrative_text }}
{% else %}
# do something else
None # displays "None"
{% endif %}
I think that the best and obvious solution would be, in Django Template language:
{% if objects is not None %}
{% for obj in objects %}
{{obj}} // Do your stuff here
{% empty %}
No results. // No results case
{% endfor %}
{% endif %}
In case the variable objects is not set, nothing will be printed out.
I had similar difficulties.
Hope it helps.
You can write Custom template filter, is_empty to check. Return false if variable is empty and true if value exists.
{% if narratives.narrative_text|is_empty %}
# dosomthing
{% else %}
# dosomthing
{% endif %}
I've used jijnja which is a lot similar and simpler and I think it would work if you do
{% if not narratives.narrative_text %}
// do something
{% else %}
// do something else with or without {{ narratives.narrative_text }}
{% endif %}
It uses python implicit True/False,None, etc to do the job.
In simplest terms use python variables inside {{ }} and conditionals,etc inside {% %}

In a Django template for loop, checking if current item different from previous item

I'm new to django and can't find a way to get this to work in django templates. The idea is to check if previous items first letter is equal with current ones, like so:
{% for item in items %}
{% ifequal item.name[0] previous_item.name[0] %}
{{ item.name[0] }}
{% endifequal %}
{{ item.name }}<br />
{% endforeach %}
Maybe i'm trying to do this in wrong way and somebody can point me in right direction.
Use the {% ifchanged %} tag.
{% for item in items %}
{% ifchanged item.name.0 %}
{{ item.name.0 }}
{% endifchanged %}
{% endfor %}
Also remember you have to always use dot syntax - brackets are not valid template syntax.

Categories

Resources