WTForms-SQLAlchemy

raw JSON →
0.4.2 verified Fri May 01 auth: no python

SQLAlchemy utilities for WTForms, including model form generation, query-based choice fields, and integration with SQLAlchemy ORM. Current version 0.4.2, requires Python >=3.9. Release cadence is sporadic.

pip install wtforms-sqlalchemy
error ImportError: cannot import name 'QuerySelectField' from 'wtforms.ext.sqlalchemy'
cause Old import path from Flask-WTF; removed in wtforms-sqlalchemy 0.4
fix
Use 'from wtforms_sqlalchemy.fields import QuerySelectField'
error TypeError: 'BaseQuery' object is not callable
cause Passing a static query object instead of a callable query factory to QuerySelectField
fix
Use query_factory=lambda: session.query(Model) or query_factory=Model.query (if Flask-SQLAlchemy)
error AttributeError: module 'wtforms_sqlalchemy' has no attribute 'orm'
cause Installed version is too old (pre-0.4) or installation is incomplete
fix
Update to >=0.4.2: pip install --upgrade wtforms-sqlalchemy
breaking 0.4 removed the old Flask-WTF compatibility layer. Imports from wtforms.ext.sqlalchemy no longer work.
fix Use wtforms_sqlalchemy.fields and wtforms_sqlalchemy.orm instead.
deprecated ModelForm class (from wtforms_sqlalchemy.orm) is deprecated in 0.4.2 and slated for removal. Use the model_form() factory function instead.
fix Replace ModelForm subclass with model_form(Model, base_class=Form, ...).
gotcha QuerySelectField and QuerySelectMultipleField require a query factory, not a static query. Passing a SQLAlchemy query object will raise 'BaseQuery object is not callable'.
fix Pass a lambda that returns the query, e.g., query_factory=lambda: session.query(Model).

Create a form model from a SQLAlchemy declarative model using model_form.

from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import DeclarativeBase
from wtforms import Form, StringField
from wtforms_sqlalchemy.orm import model_form

class Base(DeclarativeBase):
    pass

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String)

engine = create_engine('sqlite:///:memory:', echo=False)
Base.metadata.create_all(engine)

UserForm = model_form(User, base_class=Form, exclude=['id'])
form = UserForm(data={'name': 'Alice'})
print(form['name'].data)  # Alice