Flask WTF 'StringField' object has no attribute 'translate'

Hanshan picture Hanshan · Apr 29, 2016 · Viewed 12.6k times · Source

I am relatively new to Python, and I've been following the Miguel Grinberg Flask Mega-Tutorial.

I have a very simple form which, when I try to submit, I receive the following error:

AttributeError: 'StringField' object has no attribute 'translate'

Here is the form:

from flask.ext.wtf import Form
from wtforms import StringField
from wtforms.validators import DataRequired


class CreateSubjectForm(Form):
    name = StringField('name', validators=[DataRequired()])

And views.py:

@app.route('/create_subject', methods=['GET', 'POST'])
def create_subject():
    form = CreateSubjectForm()
    if form.validate_on_submit():
        subject = Subject(name=form.name)
        db.session.add(subject)
        db.session.commit()
    return render_template('create_subject.html',
                           title='Create Subject',
                           form=form)

My template is as follows:

{% extends "base.html" %}

{% block content %}
    <h2>Create Subject</h2>
    <form action="" method="post" name="create_subject">
        {{ form.hidden_tag() }}
        <div class="form-control-label">Name: </div>
        <div class="form-control">{{ form.name(size=45) }}</div>
        <input type="submit" value="Create">
    </form>
{% endblock %}

I have been unable to solve this problem, but here is what I have looked at.

One concern arose from the fact that PyCharm tells me that it cannot find wtf in flask.ext in the line from flask.ext.wtf import Form. I am using Python 2.7. From research it appears that this is the correct way to import for 2.7. I tried changing it to from flask_wtf import Form and the PyCharm error goes away, but the behaviour is the same.

From the traceback I thought it looked like something has gone wrong with versions and packages. I double check I had everything installed with pip.install and it appears I do - here is pip.freeze from the virtual environment:

Babel==2.2.0
blinker==1.4
coverage==4.0.3
decorator==4.0.9
Flask==0.10.1
Flask-Babel==0.9
Flask-Login==0.3.2
Flask-Mail==0.9.1
Flask-OpenID==1.2.5
Flask-SQLAlchemy==2.1
Flask-WhooshAlchemy==0.56
Flask-WTF==0.12
flipflop==1.0
guess-language==0.2
itsdangerous==0.24
Jinja2==2.8
MarkupSafe==0.23
pbr==1.8.1
PyMySQL==0.7.2
python-openid==2.2.5
pytz==2016.3
six==1.10.0
speaklater==1.3
SQLAlchemy==1.0.12
sqlalchemy-migrate==0.10.0
sqlparse==0.1.19
Tempita==0.5.2
Werkzeug==0.11.5
Whoosh==2.7.3
WTForms==2.1

And here is the traceback:

> Traceback (most recent call last):   File
> "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\flask\app.py",
> line 1836, in __call__
>     return self.wsgi_app(environ, start_response)   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\flask\app.py",
> line 1820, in wsgi_app
>     response = self.make_response(self.handle_exception(e))   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\flask\app.py",
> line 1403, in handle_exception
>     reraise(exc_type, exc_value, tb)   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\flask\app.py",
> line 1817, in wsgi_app
>     response = self.full_dispatch_request()   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\flask\app.py",
> line 1477, in full_dispatch_request
>     rv = self.handle_user_exception(e)   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\flask\app.py",
> line 1381, in handle_user_exception
>     reraise(exc_type, exc_value, tb)   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\flask\app.py",
> line 1475, in full_dispatch_request
>     rv = self.dispatch_request()   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\flask\app.py",
> line 1461, in dispatch_request
>     return self.view_functions[rule.endpoint](**req.view_args)   File "C:\Users\timni\onedrive\dev\studyplanner\app\views.py", line 24, in
> create_subject
>     db.session.commit()   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\sqlalchemy\orm\scoping.py",
> line 157, in do
>     return getattr(self.registry(), name)(*args, **kwargs)   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\sqlalchemy\orm\session.py",
> line 801, in commit
>     self.transaction.commit()   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\sqlalchemy\orm\session.py",
> line 392, in commit
>     self._prepare_impl()   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\sqlalchemy\orm\session.py",
> line 372, in _prepare_impl
>     self.session.flush()   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\sqlalchemy\orm\session.py",
> line 2019, in flush
>     self._flush(objects)   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\sqlalchemy\orm\session.py",
> line 2137, in _flush
>     transaction.rollback(_capture_exception=True)   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\sqlalchemy\util\langhelpers.py",
> line 60, in __exit__
>     compat.reraise(exc_type, exc_value, exc_tb)   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\sqlalchemy\orm\session.py",
> line 2101, in _flush
>     flush_context.execute()   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\sqlalchemy\orm\unitofwork.py",
> line 373, in execute
>     rec.execute(self)   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\sqlalchemy\orm\unitofwork.py",
> line 532, in execute
>     uow   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\sqlalchemy\orm\persistence.py",
> line 174, in save_obj
>     mapper, table, insert)   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\sqlalchemy\orm\persistence.py",
> line 800, in _emit_insert_statements
>     execute(statement, params)   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\sqlalchemy\engine\base.py",
> line 914, in execute
>     return meth(self, multiparams, params)   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\sqlalchemy\sql\elements.py",
> line 323, in _execute_on_connection
>     return connection._execute_clauseelement(self, multiparams, params)   File
> "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\sqlalchemy\engine\base.py",
> line 1010, in _execute_clauseelement
>     compiled_sql, distilled_params   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\sqlalchemy\engine\base.py",
> line 1146, in _execute_context
>     context)   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\sqlalchemy\engine\base.py",
> line 1344, in _handle_dbapi_exception
>     util.reraise(*exc_info)   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\sqlalchemy\engine\base.py",
> line 1139, in _execute_context
>     context)   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\sqlalchemy\engine\default.py",
> line 450, in do_execute
>     cursor.execute(statement, parameters)   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\pymysql\cursors.py",
> line 156, in execute
>     query = self.mogrify(query, args)   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\pymysql\cursors.py",
> line 135, in mogrify
>     query = query % self._escape_args(args, conn)   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\pymysql\cursors.py",
> line 115, in _escape_args
>     return dict((key, conn.escape(val)) for (key, val) in args.items())   File
> "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\pymysql\cursors.py",
> line 115, in <genexpr>
>     return dict((key, conn.escape(val)) for (key, val) in args.items())   File
> "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\pymysql\connections.py",
> line 781, in escape
>     return escape_item(obj, self.charset, mapping=mapping)   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\pymysql\converters.py",
> line 26, in escape_item
>     val = encoder(val, mapping)   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\pymysql\converters.py",
> line 109, in escape_unicode
>     return u"'%s'" % _escape_unicode(value)   File "C:\Users\timni\onedrive\dev\studyplanner\venv\lib\site-packages\pymysql\converters.py",
> line 72, in _escape_unicode
>     return value.translate(_escape_table) AttributeError: 'StringField' object has no attribute 'translate'

So at this point I am stumped. Any help will be very greatly appreciated. Thank you.

Answer

snakecharmerb picture snakecharmerb · Apr 29, 2016

The error is occurring because the Subject instance is being constructed with an instance of StringField, but what is required is the value of the StringField's data.

So instead of

subject = Subject(name=form.name)  # form.name is a StringField

do

subject = Subject(name=form.name.data) 

The clue is in the exception message AttributeError: 'StringField' object has no attribute 'translate' - translate is a string method, so it suggests that somewhere something that is not a string is being passed to something that expects a string.