Browse Source

Chapter 11: Rich text server side handling with Markdown and Bleach (11f)

master
T. Meissner 6 years ago
parent
commit
44b9042b9f
4 changed files with 53 additions and 1 deletions
  1. +15
    -0
      app/models.py
  2. +7
    -1
      app/templates/_posts.html
  3. +28
    -0
      migrations/versions/53a175284ebe_.py
  4. +3
    -0
      requirements/common.txt

+ 15
- 0
app/models.py View File

@ -2,6 +2,8 @@ from datetime import datetime
import hashlib import hashlib
from werkzeug.security import generate_password_hash, check_password_hash from werkzeug.security import generate_password_hash, check_password_hash
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from markdown import markdown
import bleach
from itsdangerous import BadSignature from itsdangerous import BadSignature
from flask import current_app from flask import current_app
from flask_login import UserMixin, AnonymousUserMixin from flask_login import UserMixin, AnonymousUserMixin
@ -191,9 +193,22 @@ class Post(db.Model):
__tablename__ = 'posts' __tablename__ = 'posts'
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
body = db.Column(db.Text) body = db.Column(db.Text)
body_html = db.Column(db.Text)
timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow) timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
author_id = db.Column(db.Integer, db.ForeignKey('users.id')) author_id = db.Column(db.Integer, db.ForeignKey('users.id'))
@staticmethod
def on_changed_body(target, value, oldvalue, initiator):
allowed_tags = ['a', 'abbr', 'acronym', 'b', 'blockquote', 'code',
'em', 'i', 'li', 'ol', 'pre', 'strong', 'ul',
'h1', 'h2', 'h3', 'p']
md = markdown(value, output_format='html')
clean_md = bleach.clean(md, tags=allowed_tags, strip=True)
target.body_html = bleach.linkify(clean_md)
db.event.listen(Post.body, 'set', Post.on_changed_body)
class AnonymousUser(AnonymousUserMixin): class AnonymousUser(AnonymousUserMixin):
def can(self, perm): def can(self, perm):


+ 7
- 1
app/templates/_posts.html View File

@ -9,7 +9,13 @@
<div class="post-content"> <div class="post-content">
<div class="post-date">{{ moment(post.timestamp).fromNow() }}</div> <div class="post-date">{{ moment(post.timestamp).fromNow() }}</div>
<div class="post-author"><a href="{{ url_for('.user', username=post.author.username) }}">{{ post.author.username }}</a></div> <div class="post-author"><a href="{{ url_for('.user', username=post.author.username) }}">{{ post.author.username }}</a></div>
<div class="post-body">{{ post.body }}</div>
<div class="post-body">
{% if post.body_html %}
{{ post.body_html | safe }}
{% else %}
{{ post.body }}
{% endif %}
</div>
</div> </div>
</li> </li>
{% endfor %} {% endfor %}


+ 28
- 0
migrations/versions/53a175284ebe_.py View File

@ -0,0 +1,28 @@
"""empty message
Revision ID: 53a175284ebe
Revises: c16f3d665442
Create Date: 2018-11-18 01:12:11.693237
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '53a175284ebe'
down_revision = 'c16f3d665442'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('posts', sa.Column('body_html', sa.Text(), nullable=True))
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('posts', 'body_html')
# ### end Alembic commands ###

+ 3
- 0
requirements/common.txt View File

@ -1,4 +1,5 @@
alembic==1.0.1 alembic==1.0.1
bleach==3.0.2
blinker==1.4 blinker==1.4
Click==7.0 Click==7.0
dominate==2.3.4 dominate==2.3.4
@ -14,11 +15,13 @@ Flask-WTF==0.14.2
itsdangerous==0.24 itsdangerous==0.24
Jinja2==2.10 Jinja2==2.10
Mako==1.0.7 Mako==1.0.7
Markdown==3.0.1
MarkupSafe==1.0 MarkupSafe==1.0
python-dateutil==2.7.3 python-dateutil==2.7.3
python-editor==1.0.3 python-editor==1.0.3
six==1.11.0 six==1.11.0
SQLAlchemy==1.2.12 SQLAlchemy==1.2.12
visitor==0.1.3 visitor==0.1.3
webencodings==0.5.1
Werkzeug==0.14.1 Werkzeug==0.14.1
WTForms==2.2.1 WTForms==2.2.1

Loading…
Cancel
Save