WTForms ships with a number of extensions that make it easier to work with other frameworks and libraries, such as Django.
This extension provides templatetags to make it easier to work with Django templates and WTForms’ html attribute rendering. It also provides a generator for automatically creating forms based on Django ORM models.
Django templates does not allow arbitrarily calling functions with parameters, making it impossible to use the html attribute rendering feature of WTForms. To alleviate this, we provide a templatetag.
Adding wtforms.ext.django to your INSTALLED_APPS will make the wtforms template library available to your application. With this you can pass extra attributes to form fields similar to the usage in jinja:
{% load wtforms %}
{% form_field form.username class="big_text" onclick="do_something()" %}
Note By default, using the {{ form.field }} syntax in django models will be auto-escaped. To avoid this happening, use Django’s {% autoescape off %} block tag or use WTForms’ form_field template tag.
Create a wtforms form for a given django model class:
from wtforms.ext.django.orm import model_form
from myproject.myapp.models import User
UserForm = model_form(User)
The form can be made to extend your own form by passing the base_class parameter. Primary key fields are not included unless you specify include_pk=True.
model_form() attempts to glean as much metadata as possible from inspecting the model’s fields, and will even attempt to guess at what validation might be wanted based on the field type. For example, converting an EmailField will result in a TextField with the email() validator on it. if the blank property is set on a model field, the resulting form field will have the optional() validator set.
Just like any other Form, forms created by ModelForm can be extended via inheritance:
UserFormBase = model_form(User)
class UserForm(UserFormBase):
new_pass = PasswordField('', [validators.optional(), validators.equal_to('confirm_pass')])
confirm_pass = PasswordField()
When combined with form iteration, model_form is a handy way to generate dynamic CRUD forms which update with added fields to the model. One must be careful though, as it’s possible the generated form fields won’t be as strict with validation as a hand-written form might be.
While linking data to most fields is fairly easy, making drop-down select lists using django ORM data can be quite repetetive. To this end, we have added some helpful tools to use the django ORM along with wtforms
Given a QuerySet either at initialization or inside a view, will display a select drop-down field of choices. The data property actually will store/keep an ORM model instance, not the ID. Submitting a choice which is not in the queryset will result in a validation error.
Specifying label_attr in the constructor will use that property of the model instance for display in the list, else the model object’s __str__ or __unicode__ will be used.
If allow_blank is set to True, then a blank choice will be added to the top of the list. Selecting this choice will result in the data property being None. The label for the blank choice can be set by specifying the blank_text parameter.
class ArticleEdit(Form):
title = TextField()
column = QuerySetSelectField(label_attr='title', allow_blank=True)
category = QuerySetSelectField(queryset=Category.objects.all())
def edit_article(request, id):
article = Article.objects.get(pk=id)
form = ArticleEdit(obj=article)
form.column.queryset = Column.objects.filter(author=request.user)
As shown in the above example, the queryset can be set dynamically in the view if needed instead of at form construction time, allowing the select field to consist of choices only relevant to the user.
This extension provides SelectField integration with SQLAlchemy ORM models, similar to those in the Django extension.
These fields are provided to make it easier to use data from ORM objects in your forms. Due to the complication of dealing with multiple-primary-keyed tables, currently it is only possible to use these fields with simple integer primary keyed ORM models.
def enabled_categories():
return Category.query.filter_by(enabled=True)
class BlogPostEdit(Form):
title = TextField()
blog = QuerySelectField()
category = QuerySelectField(query_factory=enabled_categories, allow_blank=True)
def edit_blog_post(request, id):
post = Post.query.get(id)
form = ArticleEdit(obj=post)
form.blog.query = Blog.query.filter(Blog.author == request.user).order_by(Blog.name)
Will display a select drop-down field to choose between ORM results in a sqlalchemy Query. The data property actually will store/keep an ORM model instance, not the ID. Submitting a choice which is not in the query will result in a validation error.
This field only works for queries on models with single-column integer primary keys. If the primary key is not named ‘id’, then you should provide the pk_attr with the name of the primary key field on the mapped model.
The query property on the field can be set from within a view to assign a query per-instance to the field. If the property is not set, the query_factory callable passed to the field constructor will be called to obtain a query.
Specifying label_attr in the constructor will use that property of the model instance for display in the list, else the model object’s __str__ or __unicode__ will be used.
If allow_blank is set to True, then a blank choice will be added to the top of the list. Selecting this choice will result in the data property being None. The label for this blank choice can be set by specifying the blank_text parameter.
Similar to QuerySelectField, only for model classes.
Using this field is only meaningful when using scoped sessions in SQLAlchemy, because otherwise model instances do not know how to make queries of themselves. This field is simply a convenience for using Model.query as the factory for QuerySelectField.