Why does django think these values are different? - django

In my template, I am creating a select control from the list in qualifications. I have added the comment line to try to figure out why I could not designate a given row as selected.
{% for qual in qualifications %}
<!-- form.qualid.value ({{ form.qualid.value }}) {% if form.qualid.value == qual.empqualid %}equals{% else %}does not equal{% endif %} qual.empqualid ({{ qual.empqualid }}) -->
<option value="{{ qual.empqualid }}"{% if qual.empqualid == form.qualid.value %} selected{% endif %}>{{ qual.EmpQualName }}</option>
{% endfor %}
A sample of my results:
<!-- form.qualid.value (166) does not equal qual.empqualid (558) -->
<option value="558">Gardening</option>
<!-- form.qualid.value (166) does not equal qual.empqualid (166) -->
<option value="166">General Manual Labour</option>
<!-- form.qualid.value (166) does not equal qual.empqualid (571) -->
<option value="571">General Manual Labour (Chinese)</option>
The middle row should be a match, as the qual.empqualid is the same as the form.qualid.value (at least it looks like it to me). The variable form.qualid is an IntegerField and qual is a dictionary that has a key 'empqualid' that also holds integers. I think that forms emit strings with value()? Is that a possible issue? If so how do I check or change types?
As you can see, django thinks that 166 and 166 are different in some way. Can somebody tell my how this might happen?

As I suspected, it's a type problem. It turns out that qual.empqualid was somehow not being interpreted as an integer (it is retrieved from an sql database where it is one) and so the form field form.qualid which is an integer was not considered equal.
The fix was to add |floatformat:"0" to the end of qual.empqualid so they are both being interpreted as integers. The select list now works as expected.
This is odd, because in the same template, I have another select field produced the same way which already works as expected with no floatformat filter. It also compares a database sourced field with a form IntegerField, but it works there.
Bit of a mystery.

Related

Get Value for Specific Select Option in Django Template

I am trying to get the value for a select option in my django template. I can iterate through an object like this:
<select id="id_name" name="name">
{% for x, y in form.fields.name.choices %}
<option value="{{ x }}">{{ y }}</option>
{% endfor %}
</select>
but is there any way to get a specific value eg; form.fields.name.choices.2? without looping? Thanks!
You can try
form.fields.name.choices.queryset.values.2
to get third element in a dict with your choices. Or you use
form.fields.name.choices.queryset.values_list.2
to get the choice as tuple.
See here https://docs.djangoproject.com/en/4.0/ref/models/querysets/#values and here https://docs.djangoproject.com/en/4.0/ref/models/querysets/#values-list

Remove whitespace and quote marks around option

I'm manually rendering a choice field.
<select name="basisofpricing" id="id_basisofpricing">
{% for value, object in form3.basisofpricing.field.choices %}
<option
value="{{value}}"
{% if form3.basisofpricing.initial.id == value %}
selected
{% endif %}
>
{{object.basisofrate}}
</option>
{% endfor %}
</select>
When I do this, within the browser, the option, when inspected, has quotes and space around it. For example, if Red was one of the options, it would appear like this when being inspected within the browser:
<option value="2">
"
Red
"
</option>
This spacing and these quotes do not appear on the options' text when I just render the choice field with {{form3.basisofpricing}}.
Any thoughts on how I can remove the white spacing and quotes around the option text?
Thanks!
Just try this exactly, without new line or space.
<option value="{{value}}" {% if form3.basisofpricing.initial.id == value %} selected {% endif %}>{{object.basisofrate}}</option>

Pebble Template Get Object from Key

So I have some experience with Pebble template syntax, however I'm having an issue trying to retrieve an entry from a Map by the key, and because the Pebble documentation isn't very intuitive, I've been spinning my wheels trying to figure out the proper syntax.
Basically, here's my overall logic:
{% set segmentsLength = file.value['segments']|length %}
{% for sg in range(1, segmentsLength) %}
{% set segment = file.value['segments'].value[sg] %}
<Segment type="{{ segment.value['segmentType'] }}">
<Start>{{ segment.value['start'] }}</Start>
<End>{{ segment.value['end'] }}</End>
</Segment>
{% endfor %}
However, segment is not returning the map of Segments, so Start and End are just empty. I've been able to get the values set by just having a separate loop as below, but than the xml elements won't be ordered as I need them:
{% for segment in file.value['segments'] %}
<Segment type="{{ segment.value['segmentType'] }}">
<Start>{{ segment.value['start'] }}</Start>
<End>{{ segment.value['end'] }}<End>
</Segment>
{% endfor %}
Any advice is appreciated. Thanks!

Django templates - Formatting strings

I've these variables:
#Int
user.id
#Float (e.g. X.YYYY)
profile.rating
I need these formatted like so (the ` is delimiter):
`profile.rating`
I've tried numerous ways to format them, but none worked. For example, concatenating them: ""|add:profile.rating|add:"" gave me nothing (literally, nothing).
I suspect that this is because add: is numbers-first, but converting the numbers into string with either slugify or stringformat:"" gave me, again, nothing.
How do I do this?
Do note: I need to do this with filters since the result will be passed as a parameter to an include.
Update:
Basically, I'm building a sort of modular include. It include looks like this:
<section>
...
{% if custom_section %}
<section id="{{ custom_section_id }}">
{{ custom_section }}
</section>
{% endif %}
...
</section>
which means that I can't just directly include the values in a parameter, I need the markup that will go inside the nested section.
I managed to solve this issue with this piece of markup:
{% with "<a href="\"/user/" as link_start %}
{% with profile.rating|stringformat:".1f" as rating %}
{% with user.id|slugify as id %}
{% with link_start|add:id|add:"/\">" as link %}
{% with link|add:rating|add:"/5</a>" as data %}
{% include "XX" with custom_data:data|safe %}
{% endwith %} a couple of times
Key here is the |stringformat:".1f" and the user.id|slugify since without them, djangos worthless templating language defaults on the belief all values are numerical, and thus crap comes out.
Of note is the |safe as well, as without it the language escapes the value.
Do note: I need to do this with filters since the result will be
passed as a parameter to an include.
You can pass them directly to include, as it will take context correctly.
{% include user.id %}

Django template indentation guideline

There is PEP 8 for Python, but I haven't seen a preferred indentation guideline for django templates.
What I mean is, I normally indent blocks like this:
<span>outside</span>
{% if condition %}
<span>within condition</span>
{% endif %}
<span>outside</span>
While this looks good on the editor, but it will look crap on view source like this:
<span>outside</span>
<span>within condition</span>
<span>outside</span>
It would even look worse within the HTML indentation, see below:
<div>
<span>outside</span>
{% if condition %}
<span>within condition</span>
{% endif %}
</div>
will become:
<div>
<span>outside</span>
<span>within condition</span>
</div>
While I agree having better layout in editor is way way more important, but I also get paranoid about the generated messy HTML source code.
I am currently following my own convention in django template guideline for consistency matter. The rule is simple:
Django tag does NOT increase the indentation level
HTML tag does increase the indentation level
It does not matter how many nested Django Tag you have, you should still on the same level of indentation. I consider this as the trade off for putting logic in templates which should be minimized if possible to avoid confusion.
<html>
<body>
<ul>
{% if condition %}
{% for item in menu_item %}
<li>{{ item }}</li>
{% endfor %}
{% endif %}
</ul>
<main>
{% block content %}
<p>Hello World</p>
{% endblock content %}
</main>
</body>
</html>
Side note
I am using 2 spaces for HTML indentation, because HTML tends to have a very deep nested.
For Vim user, please note that the syntax is not html but htmldjango
Thus my ~/.vimrc looks something like:
autocmd Filetype htmldjango setlocal ts=2 sts=2 sw=2 expandtab
Depending your editor, there are ways to set a specific indent width for HTML files.
As for the Django tags, it is actually a good thing not to not add a indent level. See that example:
<ul>
{% for item in items %}
<li>{{ item }}</li>
{% endfor %}
</ul>
Would be rendered like so:
<ul>
<li>Bacon</li>
<li>Ninja</li>
<li>Tumbleweed</li>
</ul>
And we do not want the two levels of indent. Instead:
{% block content %}
<ul>
{% for item in items %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% endblock content %}
My apologies for reviving an old question, but I think the way Emacs' web-mode.el indents Django templates deserves a mention here:
{% block content %}
<div
id="1"
class="fancy"
>
{% if link %}
<a href="{{ link }}">
Click here
</a>
{% endif %}
</div>
{% endblock %}
As you can see, it indents both Django tags and HTML tags, as well as multiline HTML tags. It supports <style> and <script> tags too. In fact, I like this behavior so much that I created DjHTML, a standalone indenter and a pre-commit hook that uses the same indentation rules as web-mode.
I think this is more of a personal preference and what is easy to read and easy to understand in the future (my time limit is "after six months") would be a better alternative than some cookbook recipes. What I use is a two type approach, not just for Django templates but for any language that accepts free formatting of the code. As such I format not critical portions as just left justified block of lines which is an admittedly eyesore but I tend to just ignore them so I can focus on important parts which is extensively indented, preferably in general single action per line and indented at each semantic group change thus all parent/child grouping, nested elements etc. are visible with just one look only.
{% if error_message %}
<p>
<strong>{{error_message}}</strong>
</p>
{% else %}
<table border>
<tr>
<td>
{{degerlendirme.adi}}
</td>
</tr>
<tr>
<td>
<table border>
<tr>
<td>
Tip
</td>
<td>
{{ tip }}
</td>
</tr>
<tr>
<td>
Açıklama
</td>
<td>
{{ degerlendirme.aciklama }}
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<form action="{% url 'perf:degerlendirme' degerlendirme.id %}" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="OK" />
</form>
</td>
</tr>
</table>
{% endif %}
I usually use Eclipse and there are several good HTML editing tools that you can install into that environment. I try to use them, but prefer to depend solely on indentation for ease of reading/coding/analysis cycle. That is mainly because I regularly need to use other editors, mostly vi. In this case if I rely mainly on Eclipse or whatever IDE I was using for understanding the code vi, nano or other text editors would make my life miserable.
As one of my professors said in a classroom, lots of years ago, spaces are free and tabs are even cheaper.
One last note; Once I needed to remove all white space from a Django template that was creating enormous nested tables in order to improve run time performance. Such might be needed for certain cases. In similar situations it is better to keep one working copy and generate runtime copy from that by a script or tool. I know that, there are some HTML de-clutter tools. In my case, tools I tried corrupted the template and I needed to perform that operation by hand.