I want to add a '*' before (or after) label's text in case the filed is required.
I can do this now by using this in my template:
{% for field in form %}
<label for="{{ field.name }}">
{{ '*' if field.flags.required }}{{ field.label.text }} :
</label>
{{ field }}
{% endfor %}
Is there some better way than this, at least a way to avoid adding label element manually?
That's how you do it, there is no simpler way than by checking the flag and then outputting what you want. You can change the text of the label somewhat more directly, though. You could also make a macro out of it so you don't need to copy and paste as much for each field in each template. Create a template "forms.html":
{% macro form_field(field) %}
{% if field.flags.required %}{{ field.label(text='*' + field.label.text) }}
{% else %}{{ field.label }}{% endif %}:
{{ field }}
{% endmacro %}
Then use it in other templates:
{# import the macro at the top of the template #}
{% from "forms.html" import form_field %}
{# use it in your for loop #}
{% for field in form %}
{{ form_field(field) }}
{% endfor %}
I've tried to find a better answer to this question and in my case this css trick worked very well and I did not have to alter anything else:
add a file to the-flask-wtf-project/app/static/styles/custom.css
with the following content in it:
div.required label:after {
content: " *";
color: red;
}
Then make sure to include the css in base.html (or all your templates using forms) inside the {% block scripts %}
<link rel="stylesheet" type="text/css" href="{{url_for('static',filename='styles/custom.css') }}">
I still consider myself a newbie so if this tips is off somehow please chime in.
Just my 2 cents, that I was very pleased with and could not find easily on any other thread here or elsewhere.
Following Henrik Andreasson's answer (thanks to his suggestion), I would like to add some more precision, because I spent few hours understanding how to avoid to do macros, like on the answer of davidism.
In the html file, you should add the attribute required:
<label for="{{ field.name }}" required="">
In my case, I was also doing a project on Flask with WTForms, so instead of what was written above, I did:
{{ form.field.label(required=form.field.flags.required) }}
In the css file, you should add:
label[required]:after {
content: " *";
}
which means:
after all the tags label containing the attribute required, add all the things in the dictionary.
Hope it helps.
Related
Sometime Django finds an error in a template. I Would like to comment out the row to debug but django keeps to find the error even in the comment.
For example this link give me an error because url 'prova' don't exist.
<!--Prova<br/>-->
another example: here {{ field }} give an error (and I don't know why but this is another problem)
<!--{% for field in form.visible_fields %}
{{ field.errors }}
{{ field.label }}
{{ field }}
{{ field.help_text }}
<br />
{% endfor %}-->
Maybe there's another way to comment?
Thank you
Django still parses the code; it doesn't care about HTML comments. If you want to ensure that it does not get rendered at all, you should use the Django comment tags, {% comment %}...{% endcomment %}.
For a single line, you can wrap things in {# ... #}.
See the docs.
I have the following thing in a jinja2 for loop:
{{ meal[item]['open-modal'].submit(**{ 'class':'btn btn-primary',
'data-toggle':'modal',
'data-target':'#myModal' }) }}
I need to have an index on the data-target like:
{{ meal[item]['open-modal'].submit(**{ 'class':'btn btn-primary',
'data-toggle':'modal',
'data-target':'#myModal-item' }) }}
item is the index needed in this case. Is there a way to escape item out of this "ad-hoc dictionary"? So that it takes on the same values as in meal[item]?
I need the 'data-target' attribute to render as '#myModal-0', '#myModal-1', etc.. As it stands each 'data-target' attribute gets set as '#myModal-item' for each item in the loop. In other words it sets item in the second line of code as a string.
In case it is ever helpful for someone, what wound up solving my problem was:
<form method="POST">
{{ meal[item]['open-modal'].csrf_token }}
{{ meal[item]['open-modal'].submit( **{ 'class':'btn btn-primary',
'data-toggle':'modal',
'data-target':'#myModal-' +
item|string } ) }}
</form>
Keep in mind that this is nested inside of two for loops in jinja2.
{% for meal in menu_dict %}
{% for item in meal %}
....
{% endfor %}
{% endfor %}
The point is summarized with this, basically:
'data-target':'#myModal-' + item|string
adds the postfix.
Here is my original source code.
{% extends "base.html" %}
{% block css %}
{{ super() }}
<link rel="stylesheet" type="text/css" href="/static/css/comic.css">
{% endblock %}
{% block content %}
<div id="comic">
<div id="nav-container">
{{ comic_path(int(panel_id) + 1) }}
{{ str(int('3')) }}
{{ int(panel_id) + 1 }}
{{ int(panel_id) }}
{{ isinstance(panel_id,basestring) }}
</div>
<img id="panel" src="{{ comic_path(panel_id) }}">
</div>
{% endblock %}
Focus on the nav-container id. All of those python blocks were attempted but all of them fail with a 500 Internal Server Error - an error in the application, and no errors are produced in the logs.
I don't have any further information that is relavent (the problem is truly isolated to those 5 example {{ }} blocks) , but I can answer any questions to help me figure it out.
Jinja2 template code is not Python code, only Python-like. As such you are limited to functions listed in the built-in filters and functions, plus whatever extra globals you explicitly added to template engine.
str() is not listed, nor is isinstance() and probably comic_path() is not either. str() is really not needed as that is what {{ ... }} interpolation already does, but there is a string() filter that does the same.
Generally speaking, you pass already processed data to your template, including the result of the comic_path() call.
Sometimes it is advantageous to add a function as a custom filter or as a new global. If you are using a ready-rolled integration of Jinja2 with a web framework, do look in the documentation for that framework to see if it offers an easy way to add filters or globals within its context.
If compic_path() is already a global, then int would be used like:
{{ comic_path(panel_id|int + 1) }}
as it is a filter, not a function.
i am new to django and tried to use the variable of an loop as a key for another object:
this is my views.py
...
files = Files.objects.filter(dataset__id = instance.dataset.id)
context = {'files': files, 'range': range(files.count())}
return render_to_response("test.html", context, context_instance=RequestContext(request))
and my test.html looks like this:
{% for i in range %}
<img title="{{i}}" src="{{files.i.data_files.url}}"/>
{% endfor %}
if i use files.0.data_files.url (or 1,2,3..) instead of files.i. it works, but i want to give out all images and also need the position of the image.
can you help me please?
the thing you're probably looking for is a magic variable {{ forloop.counter }} (or {{ forloop.counter0 }} if you want to use zero-based index) available inside {% for %} loop:
{% for file in files %}
<img title="{{ forloop.counter }}" src="{{file.data_files.url}}"/>
{% endfor %}
I am currently writing a django app around a rather complex data model.
For many use cases, I need to build similar, but slightly differing templates (incl. graphviz etc..).
Now I wonder if there is a way to follow DRY and create the templates "on the fly", e.g. based on a nested tuple (of which one gets defined per use-case -> template).
Practically speaking I'd like to stop writing these:
static_template_case1.html
{% if program %}
{{ program.name }}
{% for process in program.process_set.all %}
{{ process.name }}
{% for step in process.step_set.all %}
{{ step.name }}
{% endfor %}
{% for control in process.control_set.all %}
{{ control.name }}
{% endfor %}
{% endfor %}
{% endif %}
and replace it with something in the following direction:
template_generator.py
structure_case1 = ("program"("process"("step","control")))
def onTheFlyTemplate(structure):
# iterate through structure
# build template dynamically
# return template
onTheFlyTemplate(structure_case1)
I was not able to find something similar and also don't know yet where to start generating templates on the fly, nor how to integrate it.
Within the views feels like a good starting point, (instead of loader.get_template('static_template_case1.html')).
Thanks for any hint sending me into the right direction as well as your thoughts if DRY is being "overdone" here.
Ralph
Edit
I got a step closer, doing the following:
In the view:
from django.template import Template
def templateGen():
return Template("Program: {{program.count}}")
#login_required
def test(request):
program = Program.objects.all()
t = templateGen()
c = RequestContext(request,locals())
return HttpResponse(t.render(c))
So far this is only a proof of concept. The real work will be to write a smart "templateGen()" listening to the nested tuple.
How about an inclusion tag?
#register.inclusion_tag('<your-template.html>')
def get_program(program_id):
return {'program': <some logic to return your Program object>}
Your main template:
{%load my-template-tags%}
<div id="my-div">
{%get_program program_id %}
</div>
And your template file:
{{ program.name }}
{% for process in program.process_set.all %}
{{ process.name }}
{% for step in process.step_set.all %}
{{ step.name }}
{% endfor %}
{% for control in process.control_set.all %}
{{ control.name }}
{% endfor %}
{% endfor %}
You'd have to pass in your program_id to the main template.