Reputation: 123
My app is working on my main PC. I tried to clone the app to my laptop (I tried to initialize it on PC in a different directory and the problem was the same so the problem isn't with the laptop) and when initializing the db with flask db init
I got the following error:
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: race [SQL: 'SELECT race.id AS race_id, race.name AS race_name \nFROM race'] (Background on this error at: http://sqlalche.me/e/e3q8)
What I'm trying to do is in one of my forms to include a wtforms RadioField
with choices based on the race table in db. So for every row in that table I want one choice in the selection. The important part of the form looks like this:
class RegistrationForm(FlaskForm):
race = RadioField('Race', validators=[InputRequired('Choose a race.')],
choices=races, coerce=int)
And the races variable is outside the form like this (before the form itself):
with create_app().app_context():
races = [(race.id, race.name.capitalize()) for race in Race.query.all()]
I figured that this last line is the problem from the call stack:
Traceback (most recent call last):
File "/home/dareon4/workspace/test/venv/bin/flask", line 11, in <module>
sys.exit(main())
File "/home/dareon4/workspace/test/venv/lib64/python3.6/site-packages/flask/cli.py", line 894, in main
cli.main(args=args, prog_name=name)
File "/home/dareon4/workspace/test/venv/lib64/python3.6/site-packages/flask/cli.py", line 557, in main
return super(FlaskGroup, self).main(*args, **kwargs)
File "/home/dareon4/workspace/test/venv/lib64/python3.6/site-packages/click/core.py", line 697, in main
rv = self.invoke(ctx)
File "/home/dareon4/workspace/test/venv/lib64/python3.6/site-packages/click/core.py", line 1066, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/home/dareon4/workspace/test/venv/lib64/python3.6/site-packages/click/core.py", line 1066, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/home/dareon4/workspace/test/venv/lib64/python3.6/site-packages/click/core.py", line 895, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/home/dareon4/workspace/test/venv/lib64/python3.6/site-packages/click/core.py", line 535, in invoke
return callback(*args, **kwargs)
File "/home/dareon4/workspace/test/venv/lib64/python3.6/site-packages/click/decorators.py", line 17, in new_func
return f(get_current_context(), *args, **kwargs)
File "/home/dareon4/workspace/test/venv/lib64/python3.6/site-packages/flask/cli.py", line 411, in decorator
with __ctx.ensure_object(ScriptInfo).load_app().app_context():
File "/home/dareon4/workspace/test/venv/lib64/python3.6/site-packages/flask/cli.py", line 372, in load_app
app = locate_app(self, import_name, name)
File "/home/dareon4/workspace/test/venv/lib64/python3.6/site-packages/flask/cli.py", line 235, in locate_app
__import__(module_name)
File "/home/dareon4/workspace/test/shapes.py", line 5, in <module>
app = create_app()
File "/home/dareon4/workspace/test/app/__init__.py", line 43, in create_app
from app.blueprints.auth import bp as auth_bp
File "/home/dareon4/workspace/test/app/blueprints/auth/__init__.py", line 7, in <module>
from . import routes
File "/home/dareon4/workspace/test/app/blueprints/auth/routes.py", line 13, in <module>
from .forms import LoginForm, RegistrationForm, ResetPasswordRequestForm, \
File "/home/dareon4/workspace/test/app/blueprints/auth/forms.py", line 19, in <module>
races = [(race.id, race.name.capitalize()) for race in Race.query.all()]
File "/home/dareon4/workspace/test/venv/lib64/python3.6/site-packages/sqlalchemy/orm/query.py", line 2836, in all
return list(self)
File "/home/dareon4/workspace/test/venv/lib64/python3.6/site-packages/sqlalchemy/orm/query.py", line 2988, in __iter__
return self._execute_and_instances(context)
File "/home/dareon4/workspace/test/venv/lib64/python3.6/site-packages/sqlalchemy/orm/query.py", line 3011, in _execute_and_instances
result = conn.execute(querycontext.statement, self._params)
File "/home/dareon4/workspace/test/venv/lib64/python3.6/site-packages/sqlalchemy/engine/base.py", line 948, in execute
return meth(self, multiparams, params)
File "/home/dareon4/workspace/test/venv/lib64/python3.6/site-packages/sqlalchemy/sql/elements.py", line 269, in _execute_on_connection
return connection._execute_clauseelement(self, multiparams, params)
File "/home/dareon4/workspace/test/venv/lib64/python3.6/site-packages/sqlalchemy/engine/base.py", line 1060, in _execute_clauseelement
compiled_sql, distilled_params
File "/home/dareon4/workspace/test/venv/lib64/python3.6/site-packages/sqlalchemy/engine/base.py", line 1200, in _execute_context
context)
File "/home/dareon4/workspace/test/venv/lib64/python3.6/site-packages/sqlalchemy/engine/base.py", line 1413, in _handle_dbapi_exception
exc_info
File "/home/dareon4/workspace/test/venv/lib64/python3.6/site-packages/sqlalchemy/util/compat.py", line 265, in raise_from_cause
reraise(type(exception), exception, tb=exc_tb, cause=cause)
File "/home/dareon4/workspace/test/venv/lib64/python3.6/site-packages/sqlalchemy/util/compat.py", line 248, in reraise
raise value.with_traceback(tb)
File "/home/dareon4/workspace/test/venv/lib64/python3.6/site-packages/sqlalchemy/engine/base.py", line 1193, in _execute_context
context)
File "/home/dareon4/workspace/test/venv/lib64/python3.6/site-packages/sqlalchemy/engine/default.py", line 509, in do_execute
cursor.execute(statement, parameters)
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: race [SQL: 'SELECT race.id AS race_id, race.name AS race_name \nFROM race'] (Background on this error at: http://sqlalche.me/e/e3q8)
So the problem is that I don't have the db initialized when I'm running the flask db init
command and that one line needs the db to exist. This probably doesn't have a solution so I'm not asking how to correct this implementation, but how to do it correctly to have form based on rows from the db. I don't have hundreds of races so I could hardcode them in but I wanted to do it this way.
Upvotes: 0
Views: 537
Reputation: 123
So after some googling I found that you can add the RadioField
choices dynamically in the views like this:
@bp.route('/register', methods=['GET', 'POST'])
def register():
form = RegistrationForm()
form.race.choices = [(race.id, race.name.capitalize()) for race in Race.query.all()]
This is exactly what I was looking for.
Upvotes: 4