I have a python array:
a=["a","b","c","d","e","f"]
I pass this as a value to tornado render:
self.render("index.html", a=a)
In my html I have the following:
<input type="hidden" id="xxx" value="
{% for c in a %}
{{c}}
{% end %}
"/>
Which gives me the following messy output:
<input type="hidden" id="xxx" value="
a
b
c
d
e
f
"/>
I tried to use a {{c.strip()}} but that did the same thing. I also trying to mix in javascript however the javascript didn't execute after rendering to populate the value field. I want the html to be normal that is value="a b c d e f"
Does anyone know how I can achieve this?
Try Tornado's filter_whitespace feature, new in version 4.3.
{% whitespace oneline %}
<input type="hidden" id="xxx" value="{% for c in a %}
{{c}}
{% end %}"/>
{% whitespace all %}
There will still be a few extra spaces but it's much closer to what you want.
Just join the list in the backend itself.
self.render("index.html", a=' '.join(a))
And use,
<input type="hidden" id="xxx" value="{{ a }}" />
in template
The same as #Avinash answered, only in-template:
<input type="hidden" id="xxx" value="{{ ' '.join(a) }}" />
Tornado templates, unlike some other templating engines like Django or Jinja, allows arbitrary Python expressions in the templates.
Related
I read through Flask-WTF extremely simplified wiki, and couldn't understand much about what I can do with it. I am under the impression that the <form> section of the html now can only look like
<form method="post">
{{ form.hidden_tag() }}
{{ form.name }}
<input type="submit">
</form>
But I really want to style my using materialized such as:
<div class="row">
<div class="input-field col s6">
<i class="material-icons prefix">account_circle</i>
<input value="FN" id="first_name" type="text" class="validate">
<label class="active" for="first_name">First Name</label>
</div>
<div class="input-field col s6">
<input value="LN" id="last_name" type="text" class="validate">
<label class="active" for="last_name">Last Name</label>
</div>
</div>
Where can I fit {{ form.first_name }} and {{ form.last_name }} into?
EDIT: Let me elaborate on my answer a bit more:
For example, I want something like Materialized datepicker (a good pop up calendar that lets user to choose the date), this should be in the <input class='datepicker' length="50">, but now that I am replacing the whole <input> line with {{ form.date }}... I lost that privilege to edit the class and what not.
WTForms fields can be called with attributes that will be set on the input they render. Pass the attributes you need for styling, JavaScript functionality, etc. to the fields, rather than just referencing the fields. The labels behave the same way, and can be accessed with field.label.
for, value, type, id, and name do not need to be passed, as they are handled automatically. There are some rules for handling special cases of attributes. If an attribute name is a Python keyword such as class, append an underscore: class_. Dashes are not valid Python names, so underscores between words are converted to dashes; data_toggle becomes data-toggle.
{{ form.first_name(class_='validate') }}
{{ form.first_name.label(class_='active') }}
{{ form.begins(class_='datepicker', length=50) }}
Note that neither of the linked methods need to be called directly, those docs just describe the behavior when calling the fields.
In WTForms 2.1 I use extra_classes, like the line below:
1. The first way
{{ f.render_form_field(form.first_name, extra_classes='ourClasses') }}
or maybe in your case just like this:
{{ form.first_name, extra_classes='ourClasses' }}
We can also use the render_kw attribute on our form field like the second way below:
2. The second way
style={'class': 'ourClasses', 'style': 'width:50%; other_css_style;'}
first_name = StringField('First name',
validators=[InputRequired(),Length(1, 64)],
render_kw=style)
But I would prefer to use the first way.
So, I did some benchmarks to see how many requests the app could handle. It turns out that when a database operation is involved, no more than 500-560 requests/sec can be handled before timing out subsequent requests, whereas without the database layer it easily comes to a whopping 1000-1100 requests/sec.
I still didn't manage to cut the db costs in most of the pages (and I'm working on it), but there's one where this overhead can be cut: the edit page.
I have the following view which is executed when you visit http://website.com/edit. What it does is get the id parameter in the url and find the post from the db (MongoDB) with it, which then pass the iterated output to the template:
def edit(id):
item = mongo.db.documents.find_one({'_id': id})
doc = item.iteritems()
return render_template('edit.html',
content=item[0],
title=item[3],
url=item[2],
id=post[1]
)
This code is executed when you click edit in the item page, which is made like this:
{% block body %}
{{ title }}
<p>{{ content }}</p>
<div>
<a href=delete>Delete</a>
<a href=edit>Edit</a>
</div>
<form method="post" action="/post">
<input type="hidden" name="id" value="{{ id }}" />
<input type="hidden" name="url" value="{{ url }}" />
<input type="hidden" name="title" value="{{ title }}" />
<input type="hidden" name="content" value="{{ content }}" />
<div>
<h5>Your Name :</h5>
<input type="text" name="name" id="add_comment_author" />
</div>
<div>
<h5>Your Thought :</h5>
<textarea name="content id="add_comment_content"></textarea>
</div>
<input type="submit" value="Send" />
</form>
{% endblock %}
As you can see there are already hidden inputs with the needed value, but they're used for the comments.
Is it possible to do something like this?:
def edit(id):
#item = mongo.db.documents.find_one({'_id': id})
#doc = item.iteritems()
doc = request.get.previous()
return render_template('edit.html',
content=doc[0],
title=doc[3],
url=doc[2],
id=doc[1]
)
Alternatively would it be possible to have two POST in one page (one for sending a comment, the other for sending the values to the edit page?
Or maybe use Flash? But I suspect that's highly suboptimal and prone to bugs.
Typical solution is to use a caching layer like Flask-Cache and a memcached server to cache recently accessed data.
Having an edit form in the page is good. You can have as many forms as you want. Btw the common approach is to have only some sort of "templated" forms hidden that you'll then fill using jQuery os similar JS libraries.
In your example you're also passing the content field as hidden. Why? One might modify your source and change the content. :)
I am trying to render data into a template file using the following Code. The error I encounter is something like :
This page contains the following errors:
error on line 13 at column 16: AttValue: " or ' expected
Below is a rendering of the page up to the first error.
Name,Author,Status
Code
def editbook(request):
if request.method == 'GET':
name = request.GET.get('name',False)
Details = bookInfo.objects.all().filter(Name=name)
id = Details.values_list('id',flat=True)
Name = Details.values_list('Name',flat=True)
Author = Details.values_list('Author',flat=True)
Status = Details.values_list('Status',flat=True)
return render(request, 'app/add.html', {'Name' : Name, 'Author' : Author, 'Status' : Status}, content_type="application/xhtml+xml")
Template Code
<html>
<head>
<title>Add</title>
</head>
<body>
<form action="add/" method="post">
{% csrf_token %}
<p style="font-family:Courier New;color:teal">Name <input type="text" placeholder="Name of the book" name="name"></input></p>
<p style="font-family:Courier New;color:teal">Author <input type="text" placeholder="Author of the book" name="author"></input></p>
<p style="font-family:Courier New; color:teal"> Status
<select name="status">
<option value=1>Read</option>
<option value=1>Unread</option>
</select>
</p>
<input type="submit" id="booksubmit" value="Add/Edit Book"></input>
</form>
</body>
</html>
I searched through Google and I found that this somewhat like XML parsing error (Please correct me if I am wrong). Now I am stuck at this position. Please help.
EDIT Here the form for adding the book has a different method for saving the field data into database.
Your HTML is malformed for whatever type is is, html and html5.
And to be picky, your python code should be refactored as well.
Normally we define variables with lowercase letter instead of a capital so
the variables Details, Name, Author, Status should be details, name, author, status.
Further more, is your class name bookInfo spelled like that?
Classes in python should start with a capital letter so bookInfo should be BookInfo.
The proper HTML5 is this:
<html>
<head>
<title>Add</title>
</head>
<body>
<form action="add/" method="post">
{% csrf_token %}
<p style="font-family:Courier New;color:teal;">Name <input type="text" placeholder="Name of the book" name="name" /></p>
<p style="font-family:Courier New;color:teal;">Author <input type="text" placeholder="Author of the book" name="author" /></p>
<p style="font-family:Courier New; color:teal;"> Status
<select name="status">
<option value=1>Read</option>
<option value=1>Unread</option>
</select>
</p>
<input type="submit" id="booksubmit" value="Add/Edit Book" />
</form>
</body>
</html>
If you're not using HTML5 and that depends on the Doctype you've defined.
You can't use placeholders in your input fields.
The inputs need to get closed with a /> and not a </input>.
The inline styles you've provided in your html is incomplete:
style="font-family:Courier New; color:teal"
should be
style="font-family:Courier New; color:teal;"
The return you're using doesn't need a content_type you can drop that.
You're not using your template variables anywhere so that's not it but if you would like to start using them the syntax for the template language is {{ variable_name }} and in your case that would be (until you refactor)
{{ Name }}, {{ Status }} for example.
Also you're seeing this error because of the content_type since you're actively telling the browser to parse the document as xhtml+xml and that's XHTML with rules, which you're effectively breaking.
For adding the value from your Django app to your input fields do this, (without a Django Form)
<input type="text" value="{{ Name }}" />
But I would recommend using a Django Form instead.
I think you're getting this error because you're template is not 'well formed'. My guess is that there's an error in the xml that's being output.
You've declared the content type of your http response to be application/xhtml+xml. xhtml requires you to put quotes around all your attributes. You're probably missing/adding a quotation mark somewhere. I can't see from your template where that is.
Either check what your template variables ({{ Name }}, {{ Author }} and {{ Status }}) are outputting to see if they're adding in a stray quotation mark, or try changing the content type (maybe just drop the content_type parameter you're passing to the render function).
I was testing Jinja2 in a Django project and have a strange output.
When I render the form, some characters are HTML encoded (< > etc.)
In the template :
{{ form.as_p() }}
It renders to the browser :
<p><label for="id_username">Utilisateur:</label> <input autocomplete="off" id="id_username" type="text" name="username" maxlength="100" /></p> <p><label for="id_password">Mot de passe:</label> <input autocomplete="off" type="password" name="password" id="id_password" /></p>
Looking at sources :
<p><label for="id_username">Utilisateur:</label> <input autocomplete="off" id="id_username" type="text" name="username" maxlength="100" /></p>
<p><label for="id_password">Mot de passe:</label> <input autocomplete="off" type="password" name="password" id="id_password" /></p>
Does anyone know this problem ?
Jinja2 tries to be safe by HTML-escaping the data. So you have to use |safe filter.
Though I haven't used Django with Jinja2, I believe this should work:
{{ form.as_p()|safe }}
My code looks like this:
<form name="deleteUser" action="/groupmanager" method="post"><div id="x"> {% csrf_token %}
<input type="hidden" name="username" value = "{{name}}"></input>
<input type="hidden" name="groupName" value = "{{group}}"></input>
<input type="submit" name="xButton" id="xButton" value="x"></div></form>
And the code works exactly the way I want it to but now that I've added it, the layout of the page has changed. Now the button has moved onto a new line instead of being on the same line as the things before it in the code.
My code used to look like this:
<div id="x"><input type="submit" name="xButton" id="xButton" value="x"></div>
I beleave the change is in IE only ? Try adding position:relative; float:left to the css of hidden inputs.