Formatting a blog post in Flask / WTForms / Google App Engine
Here's the question in brief:
My blog posts at...
http://www.seanbradley.biz/blog
...totally lacks formatting. They're just a big block of plaintext. Any code or HTML tags such as /n or < br / > ...let alone h1, h2, etc...have no demonstrable effect on the way text appears on the page.
I'm running Flask with WTForms deployed on GAE. How can I fix this? Is there a way to implement a WYSGIWYG editor--like TinyMCE--into the form field for new blog post entries?
I'm going for a look as simple and elegant as...
http://www.quietwrite.com
or
http://lucumr.pocoo.org/
...or at a minimum something akin to Stackoverflow's own editor.
Formatting is rendered in the posts in all of the above upon publication (rather than via the grody overblown toolbar of an editor).
I'm not sure if what's prohibiting HTML tags from rendering in my posts is related to customization of a class in WTForms, or something which must be treated specially in GAE's datastore, or something I need to fix within Flask (eg, the model for posts). Any clear solution on how I--as a relatively junior dev--can incorporate formatting into these blog posts earns the bounty. Specific code from the app below...
Note: there's also a Flask-Markdown extension, but I'm equally unsure as to how to integrate it to achieve the effect I want.
The question in detail, plus snippets from the code base
I'm running Flask (with Jinja templates / Werkzeug routing, of course) on Google App Engine, and confused about how to integrate a WYSIWYG editor into the page I have dedicated for blog posts...
I'm assuming, if incorporating TinyMCE, the call for the JavaScript goes in the header of the template...like so:
<script type="text/javascript" src="/static/js/tiny_mce/tiny_mce.js">
But, then--because, per se, there's no within the template or the rendered page itself, it's not merely--per TinyMCE's install docs--a matter of also adding the following block of code into the template...
<textarea cols="80" rows="10" id="articleContent" name="articleContent">
<h1>Article Title</h1>
<p>Here's some sample text</p>
</textarea>
<script type="text/javascript">
tinyMCE.init({
theme : "advanced",
theme_advanced_toolbar_location : "top",
theme_advanced_toolbar_align : "left",
mode : "exact",
elements : "articleContent"
});
</script>
Presently, within the tags of the template file...
<label for="title">{{ form.title.label }}</label>
{{ form.title|safe }}
{% if form.title.errors %}
<ul class="errors">
{% for error in form.title.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<label for="prose">{{ form.prose.label }}</label>
{{ form.prose|safe }}
...more WTForm validation / error handling...
I suspect the problem is in the way the form is constructed / managed via WTForms. WTForms resides in my /packages/flaskext directory. Is something like the following required somewhere...?
class wtforms.fields.TextAreaField(default field arguments, choices=[], coerce=????????, option_widget=????????)
But TextAreaField is imported from (I don't know where)...and don't know if that's even the right place / thing to tweak. Is the answer in the init.py, file.py, and/or html5.py of the WTForm module?
Again, I'd be happy if just HTML tags I include in the post are rendered upon publication...but slick way to make it easy for someone who is not accustomed to HTML to likewise format their posts would be doubly appreciated. Any help pointing me in the right direction is super appreciated!
Add'l code, if needed, follows...
I have the following class in my models.py...
class PostModel(db.Model):
"""New Post Model"""
title = db.StringProperty(required = True)
prose = db.TextProperty(required = True)
when = db.DateTimeProperty(auto_now_add = True)
author = db.UserProperty(required = True)
And the following class in my forms.py...
class PostForm(wtf.Form):
title = wtf.TextField('Title: something buzz-worthy...', validators=[validators.Required()])
prose = wtf.TextAreaField('Content: something beautiful...', validators=[validators.Required()])
The issue of having your HTML be HTML-encoded is most likely an issue that happens at render time rather than at writing time. When you receive the data back and persist it in the datastore if your HTML is still HTML and not <tag>
then you need to mark your rendering as safe:
{% for post in posts %}
<h2>{{ post.title | safe }}<h2>
<article>{{ post.content | safe }}</article>
{% endfor %}
Also, in WTForms, Field.Label
(as in form.prose.label
) actually renders a full label (no need to wrap the call to it in pre-rendered labels.)