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.
Related
In a template, I have a variable of type list called "participants". I want to check if the length of the list is equal to 2, for example. I tried the following:
{{ participants | json_script:"participants"}}
{% if participants|length==2 %}
.....
{% endif %}
However, this does not work. The error I get is:
TemplateSyntaxError at /chat/lobby/
Could not parse the remainder: '==2' from 'participants.count==2'
Can someone point out a way to access a list's length in a template's code block? thank you for your time and consideration!
The problem is the (lack of) spacing around the == part. If you rewrite this to
{% if participants|length == 2 %}
…
{% endif %}
the template parser will no longer error.
That being said, a template is used for rendering logic, and while it is hard to tell, it looks that this is more business logic, which, as #MeL says belongs in the views.
I need to apply a if-else logic based on a static minion id inside a state file. The target glob qualifies a whole bunch of servers, but I need to run a small piece of logic on a single server and run a bunch of common things on all of them. How can I do this?
When I put this in a Jinja file, its errors:
{% import salt.config %}
{% minion_opts = salt.config.minion_config('/etc/salt/minion') %}
{% print(minion_opts['id']) %}
{% if minion_opts['id'] == 'xyz.server': %}
-- run the logic here
..
..
Error:
- Rendering SLS 'base:bin.test' failed: Jinja syntax error: expected token 'as', got 'end of statement block'; line 1
-
- ---
- {% import salt.config %} <======================
- {% minion_opts = salt.config.minion_config('/etc/salt/minion') %}
- {% print(minion_opts['id']) %}
It probably goes without saying I am not a Saltstack expert by any means.
So first off, I realize this is an old question, but it still shows up at the top of the my search results for both DDG and Google for a somewhat related problem and the current answers don't really deliver on the ask, so here's an answer based off the latest SaltStack version (3002):
In order to get control flow working for Jinja based off minion id:
{% if salt['grains.get']('id') == 'minion_a' %}
some text to render for minion_a
{% else %}
some text to render otherwise
{% endif %}
I realize there were other issues in how the question was phrased and for the sample code provided, but my code snippet answers the actual question of:
I need to apply a if-else logic based on a static minion id inside a state file.
How can I do this?
The error occurs because you're using Jinja's import in an unexpected way. If this is a Flask app, you should use something like this in your views.py route to provide variables to the template:
render_template('my_template.html', salt=salt)
The corrected code should look something like this:
{% set minion_opts = salt.config.minion_config('/etc/salt/minion') %}
{{ minion_opts['id'] }}
{% if minion_opts['id'] == 'xyz.server' %}
{{ 'logic goes here' }}
{% endif %}
See the Assignments docs on how to assign values to variables.
No colon is necessary at the end of the if statement, and remember to use {% endif %} after you're done with your conditional statements.
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.
Hi I am using App Engine/Python to do a simple website. I have some trouble with a Django template problem.
In short, I want to use a "ShortName" to access a "LongName".
The soource code:
LongName={"so":"stackoverflow","su":"superuser"}
ShortName=['so','su']
Then I pass these two parameters to the templates.
In the template I write:
{% for aname in ShortName %}
{{ aname }} stands for {{ LongName.aname }},
{% endfor %}
The output is:
so stands for, su stands for
No error is given. The LongName.aname wont work.
I have no idea whats wrong.
This is trying to access LongName['aname'], not LongName[aname].
You might have to write a custom template tag/filter to get this to work. This Django bug (marked WONTFIX) has a simple implementation:
def get(d, key):
return d.get(key, '')
register.filter(get)
which you would use by
{{ LongName|get:aname }}
after adding it to your app (that SO answer shows how to do it on GAE).
You could also pre-make a variable to loop over in the view, by passing in
# in view
name_abbrevs = [(k, LongName[k]) for k in ShortName]
# in template
{% for short_name, long_name in name_abbrevs %}
{{ short_name }} stands for {{ long_name }}
{% endif %}
If you really don't want to add a template tag -- which isn't that bad! you just make one file! :) -- or pass in an extra variable, Vic's approach will let you do this without touching the Python files at all. As he mentions, it involves a lot of pointless iteration, but it'll work fine for small lists.
Django templates have a drawback here. I've been in the same situation before. What you have to do is iterate over all the keys in LongName, and check if the key you're looking for matches the ShortName. Here you go:
{% for aname in ShortName %}
{% for short_version, long_version in LongName %}
{% if aname == short_version %}
{{ aname }} stands for {{ long_version }},
{% endif %}
{% endfor %}
{% endfor%}
It's inefficient, and essentially a pointless O(n^2) mechanism. However, there's no better way in pure Django templates to refer to entries of a dict by a variable name.
How can you perform complex sorting on an object before passing it to the template? For example, here is my view:
#login_required
def overview(request):
physicians = PhysicianGroup.objects.get(pk=physician_group).physicians
for physician in physicians.all():
physician.service_patients.order_by('bed__room__unit', 'bed__room__order', 'bed__order')
return render_to_response('hospitalists/overview.html', RequestContext(request, {'physicians': physicians,}))
The physicians object is not ordered correctly in the template. Why not?
Additionally, how do you index into a list inside the template? For example, (this doesn't work):
{% for note_type in note_types %}
<div><h3>{{ note_type }}</h3>
{% for notes in note_sets.index(parent.forloop.counter0) %}
#only want to display the notes of this note_type!
{% for note in notes %}
<p>{{ note }}</p>
{% endfor %}
{% endfor %}
</div>
{% endfor %}
Thanks a bunch, Pete
As others have indicated, both of your problems are best solved outside the template -- either in the models, or in the view. One strategy would be to add helper methods to the relevant classes.
Getting a sorted list of a physician's patients:
class Physician(Model):
...
def sorted_patients(self):
return self.patients.order_by('bed__room__unit',
'bed__room__order',
'bed__order')
And in the template, use physician.sorted_patients rather than physician.patients.
For the "display the notes of this note_type", it sounds like you might want a notes method for the note_type class. From your description I'm not sure if this is a model class or not, but the principle is the same:
class NoteType:
...
def notes(self):
return <calculate note set>
And then the template:
{% for note_type in note_types %}
<div><h3>{{ note_type }}</h3></div>
{% for note in note_type.notes %}
<p>{{ note }}</p>
{% endfor %}
</div>
{% endfor %}
"I'd like to do this from within a template:"
Don't. Do it in the view function where it belongs.
Since the question is incomplete, it's impossible to guess at the data model and provide the exact solution.
results= physician.patients.order_by('bed__room__unit', 'bed__room__order', 'bed__order')
Should be sufficient. Provide results to the template for rendering. It's in the proper order.
If this isn't sorting properly (perhaps because of some model subtletly) then you always have this kind of alternative.
def by_unit_room_bed( patient ):
return patient.bed.room.unit, patient.bed.room.order, patient.bed.order
patient_list = list( physician.patients )
patient_list.sort( key=by_unit_room_bed )
Provide patient_list to the template for rendering. It's in the proper order.
"how do you index into a list inside the template"
I'm not sure what you're trying to do, but most of the time, the answer is "Don't". Do it in the view function.
The template just iterate through simple lists filling in simple HTML templates.
If it seems too complex for a template, it is. Keep the template simple -- it's only presentation. The processing goes in the view function
You should be able to construct the ordered query set in your view and pass it to your template:
def myview(request):
patients = Physician.patients.order_by('bed__room__unit',
'bed__room__order',
'bed__order')
return render_to_response('some_template.html',
dict(patients=patients),
mimetype='text/html')
Your template can then loop over patients which will contain the ordered results. Does this not work for you?
EDIT: For indexing, just use the dot syntax: mylist.3 in a template becomes mylist[3] in python. See http://docs.djangoproject.com/en/dev/ref/templates/api/#rendering-a-context for more information.
This is one way of doing it, although very ugly :
{% for note in note_sets|slice:"forloop.counter0"|first %}