1

I have been following along the lines of Miguel Grinberg's Flask Web Development. While building a blog I am unable to understand what the error (that I am getting) is and whether it is due my code or because of the extensions that I am using.

   File "/home/abhinav/projects/sample/app/blog/views.py", line 51, in edit
    blog.body=form.body.data,
  File "/home/abhinav/projects/avenues-flask/venv/lib/python2.7/site-packages/sqlalchemy/orm/attributes.py", line 224, in __set__
    instance_dict(instance), value, None)
  File "/home/abhinav/projects/avenues-flask/venv/lib/python2.7/site-packages/sqlalchemy/orm/attributes.py", line 696, in set
    value, old, initiator)
  File "/home/abhinav/projects/avenues-flask/venv/lib/python2.7/site-packages/sqlalchemy/orm/attributes.py", line 705, in fire_replace_event
    self._init_append_or_replace_token())
  File "/home/abhinav/projects/avenues-flask/venv/lib/python2.7/site-packages/sqlalchemy/orm/events.py", line 1534, in wrap
    fn(target, value, *arg)
  File "/home/abhinav/projects/sample/app/models.py", line 368, in on_changed_body
    markdown(value, output_format='html'),
  File "/home/abhinav/projects/avenues-flask/venv/lib/python2.7/site-packages/markdown/__init__.py", line 494, in markdown
    return md.convert(text)
  File "/home/abhinav/projects/avenues-flask/venv/lib/python2.7/site-packages/markdown/__init__.py", line 355, in convert
    if not source.strip():
AttributeError: 'tuple' object has no attribute 'strip'

In order to insert images and other stuff to posted as HTML, I am using the following snippet in my models.py file: I got part of the snippet from here.

class Blog(db.Model):
    __tablename__ = 'blogs'
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(64), unique=True, index=True)
    body = db.Column(db.Text)
    summary = db.Column(db.Text)
    timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
    author_id = db.Column(db.Integer, db.ForeignKey('users.id'))
    body_html = db.Column(db.Text)
    summary_html = db.Column(db.Text)

    @staticmethod
    def on_changed_body(target, value, oldvalue, initiator):
        allowed_tags = ['a', 'abbr', 'acronym', 'b', 'blockquote', 'code',
                        'em', 'i', 'li', 'ol', 'pre', 'strong', 'ul',
                        'h2', 'h3', 'p', 'img', 'video', 'div', 'iframe', 'p', 'br', 'span', 'hr', 'src', 'class']
        allowed_attrs = {'*': ['class'],
                         'a': ['href', 'rel'],
                         'img': ['src', 'alt']}
        target.body_html = bleach.linkify(bleach.clean(
            markdown(value, output_format='html'),
            tags=allowed_tags, strip=False, attributes=allowed_attrs))


    @staticmethod
    def on_changed_summary(target, value, oldvalue, initiator):
        allowed_tags = ['a', 'abbr', 'acronym', 'b', 'code', 'em', 'i',
                    'strong']
        target.summary_html = bleach.linkify(bleach.clean(
            markdown(value, output_format='html'),
            tags=allowed_tags, strip=True))

db.event.listen(Blog.body, 'set', Blog.on_changed_body)
db.event.listen(Blog.summary, 'set', Blog.on_changed_summary)

I also see some undesired characters in fields that I have. These characters can be seen in the title field as well as the Blog Entry Content section. This is also noted here.

The undesired characters can be seen in the title field as well as the Blog Entry Content section.

EDIT

I am adding my function

def edit(id):
    blog = Blog.query.get_or_404(id)
    if current_user != blog.author and \
            not current_user.can(Permission.WRITE_BLOG_ARTICLES):
        abort(403)
    form = BlogForm()
    if form.validate_on_submit():
        blog.title=form.title.data,
        blog.body=form.body.data,
        blog.summary=form.summary.data
        db.session.add(blog)
        flash('The blog has been updated.')
        return redirect(url_for('.entry', id=blog.id))
    form.title.data = blog.title,
    form.body.data = blog.body,
    form.summary.data = blog.summary
    return render_template('blog/edit_blog_post.html', form=form)
Community
  • 1
  • 1
spunkpike
  • 94
  • 2
  • 13

1 Answers1

3

Do you use the interactive debugger in flask? It allows you to examine each level of the traceback and see what the variables are.

If you trigger the error with the debugger, then expand this line of the traceback:

  File "/home/abhinav/projects/sample/app/models.py", line 368, in on_changed_body
    markdown(value, output_format='html'),

And examine the contents of value, I'm guessing it will be a tuple instead of a string.

You could also use a print statement before this line to examine the contents:

    ...original code...
    print value
    target.summary_html = bleach.linkify(bleach.clean(
        markdown(value, output_format='html'),
        tags=allowed_tags, strip=True))
    ...

(but I really recommend the debugger over print debugging! it's much nicer)

If value really is a string there, then you can repeat the same process in the surrounding levels of the traceback. That will tell you if it is being turned into a tuple inside the markdown package, which may be a bug in the library itself, or if there is some other issue in your code. This method of debugging will let you zero in on where the problem lies.

As for your note about the "undesired characters", do you mean this?

(u'Block quote should finally work.. Well',)

If you see this in your final output it means you are somehow passing a tuple around somewhere instead of a string.

>>> title = (u'Block quote should finally work.. Well',)
>>> type(title)
<type 'tuple'>
>>> title.strip()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute 'strip'

#vs..

>>> title = u'Block quote should finally work.. Well'
>>> type(title)
<type 'unicode'>
>>> title.strip()
u'Block quote should finally work.. Well'

In response to the new code you posted, look at these lines:

form.title.data = blog.title,
form.body.data = blog.body,

The trailing comma creates a tuple of one element:

>>> 'a',
('a',)
>>> x = 'a',
>>> type(x)
<type 'tuple'>

Remove the stray commas and that should solve at least one of your problems.

Steven Kryskalla
  • 14,179
  • 2
  • 40
  • 42
  • Thank you for such a great answer. I tried what you have written and I still could not resolve my issue. Both `blog.body` and `form.body.data` are coming out to be unicode type. I have added my function to question. Can you give any suggestions? – spunkpike Jul 30 '15 at 04:36
  • Okay. I got it. blog.title is being passed as tuple. But I still do not know why. – spunkpike Jul 30 '15 at 05:23
  • 2
    Yes! Try looking at the contents of `value` in the debugger instead of `blog.body` and `form.body.data`, it should be a tuple. I just added more information to my answer. If this helped you don't forget to mark an [accepted answer](https://stackoverflow.com/help/accepted-answer)! Happy hacking :) – Steven Kryskalla Jul 30 '15 at 05:25